#Railbound Solver [Python Script] COMPLETE! Working on Interface...
1 messages ยท Page 2 of 1
mashing the cars and decoys together is so frustrating theyre polar opposites but theyre so similar in how they work
considering ill still have to add in world 11's mechanic i might add a 6th variable to the cars just indicating what type it is
instead of relying solely on the car number
yeah
i think to fix the whole issue of not being able to remove stuff while its generating i can iterate over a copy of the cars instead of the actual cars
i will try that
doing the fencepost might cause some problems now that i think about it because cars dont check if the tile directly in front of them will crash it
cause it always checks if the tile 2 tiles in front will crash it to make the branches shorter when generating
ex. a car is following directly behind a decoy and the decoy crashes, there is now a fence in front of the car which it wont check because its directly in front of it
couldnt have seen it 2 tiles ahead either because the decoy is directly in front of it
aghhh my need for optimization and for stuff to be as fast as possible is killing me
i think im going to go with the just looping over all the cars and if a decoy crashes then the tile it says it wants to place can be like -1 or 0 and the program picks that up and removes it from the list
i do a loop for switches before generation, then a loop for generation, and then a loop for checking crashes so it makes sense kinda
crashes for cars are detected in generation because its faster and they dont need to remove anything, they can just kill the program and be done there cause car crashes mean the level isnt gonna be completed
so decoys need their own crash handling after generation to actually alter the lists
i do the same thing with cars that have reached the finish because i cant alter the list to say they've finished it until its done generating
actually speaking of this same-tile collisions are detected after the loop while head-on's are detected inside it and i could probably move same-tile inside there
will check for an iteration comparison actually and do that first
ALSO! another thing on checking the maximum heatmap limit for boards:
i think when i want to figure that out i can alter the system slightly so it doesnt check for the best track count but instead checks for the solution with the highest heatmap value and then figure out what the max is for levels
same-tile detection outside gen loop vs same-tile detection inside gen loop
very confused on why it has more iterations
ok the inside detection doesnt work one moment
accidentally used the list with the original cars instead of the ones that moved, since im doing the detection in the array now i have to compare a generating's car position ahead of it to a car that has already generated and check if theyre on the same tile
ok i fixed it
it has a few more iterations
i would expect it to have less
ya i have no idea
i shall move it out then i guess
- doing the crash detection in the loop requires a looot more loops to go over all the cars and see if any are crashed
i dont think i can do the same for head-ons because generation is done in game movements so the cars just pass through each other
i think for decoys crashing im just going to act like the car is stalled indefinitely
for now at least
mmm i cant do that because stalling works specifically for gates
i might need to add another variable
actually that wont be very ideal because ill have to continue to add the info to the cars being generated that its in the same position (that wastes time)
the fence idea could still work id just have to add in the thing that checks if the tile in front of it will crash it
gahhh the board wont be displayed properly if i make the tile a fence...
youd have to guess what tile would be there which is not good in terms of readability
cause the tile that should be there would just look like a fence
it technically solved it though :)
(7-1)
i think ill inevitably just need to make an extra variable that marks where decoys have crashed
yess
only took a few additions of code 
i only added it for if the car hit the border though so i just need to add it for everything else
adding it for crashing is definitely going to be a bit more complicated though
gonna call for now until tomorrow though, should hope to see world 7 dominated by then
the speed at which i can do these new mechanics with v5.1 is insane
its so much simpler to manage because it uses actual game logic
to move on 7-2's decoy solution requires that the decoy crashes into an empty tile which might be problematic
i could try and make it so placing an empty tile is an option but then it isn't technically placing a tile and making that one specifically not place while still being in the selection for tracks to generate would be annoying...
i dont really see any other solution though because placing nothing has to always be an option for decoy cars in case they can do that and have an extra track
the main problem is the system that kills boards if theyre under or equal to the minimum tracks solution
so actually.. i could easily check whether or not thats possible by just checking if placing a track wouldn't beat the best solution, in which case the only placing option would be an empty tile
the problem of branching with different available tracks is still a problem though
cause right now i can just pass a single available_tracks variable because of how generation works, there is never an instance where a car can both place a track and change one, it either changes tracks, leaves them the same, or places new ones. they never combine
but since decoys can do that i need to account for it...
i think during the final board setup for the next game movement of a generation if an empty tile is included in the board then ill add 1 to the available_tracks just for that branch
actually that wouldnt work cause theres still the option the only placable track is 0 in which the counter wouldnt go down so it cant be changed, but for the option where its 0 and the rest of the generatable tracks there then id need to detect the 0 to be changed
and there wouldnt be a difference between the 0 where the tracks dont need to be changed and the 0 where they do
im gonna try negating it by 1 no matter what when it places 0's, ignore the thing that kills it if it's worse than the best solution, and then add 1 available track to any generation that places a 0
actually
i could just do another combination checker like i do for the entire generation system that provides different combinations of the tracks placed and cars it does for each game movement and add a combination for the tracks too
itd waste resources since it only applies for when a "0" track is placed (empty tile) but i think the combination maker is fast enough that it shouldnt matter
im gonna test a level that takes some time and see if there's any difference
actually appending it would take time
i wonder if there's any other way
i could add ANOTHER variable that tells whether or not to negate the tracks if a specific car chooses to place nothing
actually that'd work well
because i wouldnt need to pass it through to the next game movement
so it wouldnt be adding more variables to the generation 
mmmm i just realized its even more complicated now because theres a chance the decoy either crashes or doesnt during a turn so i have to decide on that now too
actually
when i made the first board solver for decoys (7-1 i showed earlier) i made it so it only removes decoys that crash once the next game-movement has started, not after its been generated
that way a branch isnt needed and it still gets the job done
so that would solve the crashing aspect
i dont think i can do the same for 0 tiles though because they have to be done before the next game movement
i just cant winnn
so placing a 0 tile wont even work because how the tile placing works after all the generation is done it places the track for each car at their respective positions
but i cant place a 0 because the car needs to be on the same tile when it crashes, but if it were to place a 0 tile it would need to be on the tile in front which is impossible
i think what i can do is just make it so if the tile it wants to place is a 0 it doesnt do place it but still does all the other stuff
decoys r so annoying
theyre making everything complicated and not simple 
now that the 0 placing is figured out (i hope) i just need to make crashing work i think and the first version of decoys should be done
then a bunch of bug fixing
good god
making it so the decoy can choose whether it wants to crash or not is actually messing everything up
i cant just return false if crashes happen now because the decoy can choose whether it wants to be on the tile its on or if it wants to be a tile ahead with how crashing is
the solution i did for all the branching stuff to prevent needing extra variables to pass on through generation was to do it all at the start of the next game movement instead of at the end of the first one
which is really annoying because it wastes resources going through a bunch of different branch combos of cars and tracks when theyre all gonna have a same-tile collision
previously i could do it right after a generation was complete but now that decoys exist and decide whether or not they wanna move or crash i need to do all of it on the next game movement
ughghghghghhhgjdalfgj
7-2 doesnt work
ok when the board is checked to see if its solved it does that by seeing if the final car going into the train matches the LAST CAR in the original cars from the data in the level
normally thatd work because the list would be like (0, 1, 2) for the original cars and then the solved order would be (0, 1, 2) and match because the last values are both 2
when i use decoys since the list has to contain both of them i mash it together
decoys are represented with their own numbers for when i do heatmaps too so the list would look like
(0, 1, 0) because car 1, car 2, then decoy 1 so the ends would never be 1 and 1 and it would never solve
i dont need to mash together the original cars list thankfully i can just put that value in for generation so it should be good
2 down so far
i still need to add all the heatmap stalling and looping shenanigans
ok for 7-3 it thinks the car is stalled and kills it after the decoy hits the switch
pretty sure its because the cars go one-by-one or something
i have a general idea of what the issue is but not precisely
the program removes crashed decoys before checking for any switch stuff

it can also do 7-3A but it crashed on 7-3B so now i have to add the loop stuff in
after that the only issue should be allowing decoys to crash with each other and then world 7 should be good
im debating if i should add another variable to count the amount of looped cars every game movement or if i should use a slow numpy method
actually i can just use the numpy method once to test on the last decoy car to see if the others are also looped
that way it doesnt get used multiple times uselessely
on second thought since i use a car number of -1 to indicate a car is crashed ill just use -2 to indicate its looped
then i can just see if theyre all looped
ok i was messing with a bunch of stuff, went back to confirm world 6 to make sure i didnt mess with any vital generational stuff
it did take x3 as long which is a let-down but it could be because i have steam and railbound open right now and frankly x3 is not bad when the program can go this fast so i dont really care
what i DO care about though...
i looked over the levels to make sure there wasnt anything sketchy and i actually noticed 6-9d has 1 more track to its solution than the guide
the guide says it has 1 but the solution says 2
yup!!! it works!!!
i feel so silly for putting it in but not checking if the tracks were better or not
guide is now down 6
i love finding better solutions it makes me so happy
@tranquil sinew not sure if you would consider this a "game-breaking" solution but i find it noteworthy as you dont need to use the left side at all
surprised it wasnt found at all when the solution is really straight...
i suppose it still does use the buttons on second thought which is a given so nevermind
back to picking apart world 7 with more motivation than before 
i am very confused.
i cant tell whether or not the game is wrong or the program is wrong here
im pretty sure the car is supposed to move, not crash
the frame the decoy touches the switch the first car should be ready to move the next turn and the 2nd car should just be following behind...
im so confused
are they supposed to crash?
are switches detected after the car exits that tile or something
yeah the car is supposed to move
?
im so confused rn
the car is 100% supposed to move wth
as soon as the switch is pressed the car should be able to move
Luke please explain why this isnt valid
i am now just realizing that the solution wouldnt work anyways because the gate at the end prevents the cars from continuing but my point still stands that they crash instead of car 1 moving forward
ok 7-4 wasn't working and i think i figured out why
when the different combinations are made for all the boards and cars each game movement, for tracks they're just placed on the board over each other
so if the first combination was (1, 1) and the 2nd was (2, 2) then for the (2, 2) combo it would overwrite the (1, 1) combo by placing the 2's on those tiles
normally this works fine but when 0's are placed they arent placed because of all the decoy shenanigans it causes
so if a decoy is planning on placing a 0 ill just do some quick math to get the position ahead and set that to 0 i guess
7-4 is killing me
the solution doesnt work because how the decoys crash is they go onto a tile, and then the next game movement they "decide" to crash which means a crash takes a game movement longer than it should
and if said decoy is on a switch when it chooses to crash it does it for both of those game movements
i can try saying the car is stalled for the first game movement so it cant press the switch again but idk if thatll backfire in the future
i shall try it for now
yesss
levels up to 7-5 work now
not sure why 7-5 doesnt work but ill figure it out next time
i really hope i dont have to change a bunch of stuff for the new gate order or whatever i just figured out
decoys are enough to handle
yeah, as long as it uses all of the existing elements on the map I'm ok with it; but it's a nice find ๐
luke?
the gate is opened at the same time the crash detection occurs because the other car tried to enter the tile that was already occupied
IMO the logic is handled as expected, but it's not represented well visually through the game's graphics
๐ค your crash detection might be different from mine then
i have a loop for all the cars to do anything with switches prior to movement, then a loop for all the game movement
for every car that does its game movement loop it checks for head-on collisions and tunnel crashes
then after the game movement loop it checks for any same-tile collisions before going to the next tile
i think what i can try is putting all the crash detection before the switch loop because head-ons can actually be outside of it possibly now that i think about it
tunnel collisions are still gonna have to be in the loop cause tunnel calculations should be done once and i cant think of any way a gate would cause a tunnel crash
ok moving the crash detection sorta did its job but not really
its not really getting anything different for like world 6 but it found an impossible solution on 6-9C
yeah no its finding faulty solutions nevermind
ugh
im gonna deal with that new crashing stuff once world 7 is done
oh yeah it also took like twice or 3 times the time to finish
ok figured out why 7-5 wasnt working
the decoy attempts to make a 3-way that loops it back around which shouldnt happen
normally for other cars i have heatmaps on them that prevents them from making 3-way that mess car movement and other stuff up but since i removed the heatmaps from the decoy for looping it cant use it
so what i think ill do is use the heatmap for the decoy but not use it at all for the heat map limit or crashing or anything
plus i dont have to reset it because it still works as a loop detector after all the other cars crashed
sweet
the only thing i have to finish now is making it so decoys can crash i think
then i can finish up world 7 and figure out how to do the new gate thing i found
im gonna add the crash system before i do 7-5a because the level itself is really complicated
so ill do 7-6 and the levels after it then do the crash system and come back
ok 7-6 and 7-5a didnt work firstly because theres 2 decoys and with how the list management works it doesnt do it properly so i just need to fix that and then do crashing
i think
the main problem was it removed list things in ascending order (1, 2, 3) so when it removed stuff from lists the indices would get messed up cause the list shifts when you remove something
so i just made it descending as that doesnt affect the list shifting
gonna try the rest of world 7 now.. only need crashing decoys added
beat the guide by 3 more tracks racking it up to beating the guide by 9 now 
(7-7C)
@tranquil sinew sorry for the pings 
this solution doesnt need the decoy, not sure if you'd consider this one game-breaking? but at the same time i guess the decoy causes more confusion when solving? not sure
i tried all of the levels but 7-5a didnt work so i just need to fix that one up, and then fix the gates and i can just chill through world 8 because theres no new mechanics there 
figured out why 7-5a errored (the first time at least)
when checking for stalled stations, i have an if statement checking if the car number is station stalled, and also if it isnt a decoy
the problem is it checks for both of those at the same time, so if there were only 1 car (meaning the highest index in station stalled is 0) that means if a decoy tried to check the 1st index of station stalled itd error
normally it wouldnt be a probem because it doesnt work anyways if its a decoy but it still checks it so i just have to stack if statements
less clean but 
2nd error!
it thinks the decoy can reach the end which im pretty sure i prevented but i guess not 
ok... another confusing game mechanic just hit me
for 7-5a (the one above i just sent) the solution was incorrectly done because the decoy reaches the end after the car finishes, and the program didnt check for it
so i added that in and...
7-4b doesnt work.
...but it kind of makes sense
the solution for 7-4b is this.
if you think about it, it should technically be a faulty solution because the decoy would loop around again and connect to the train eventually
but it works.
the one i showed for 7-5a however, does not
so this begs another question for luke...
how does decoy finishing work?
what it seems to me like is that the decoy moves either 1 or 2 game movements and then finally stops
ok... i added another variable that gets passed through generation (yippee...) that records the amount of game movements after all the cars have been solved
im gonna make it count to 2 before it counts the solution as valid but i still have to deal with some shenanigans cause after a car solves theres no cars in the cars to use and that can be problematic depending on if theres decoys or not
...closer
it can do all the world 7 levels now but i have yet to add in decoy crashing which is why im not getting the 6 extra tracks i should be for 7-5a
42 minute level huh...
ok... so while figuring out how to do decoy crashing i need to think about what tiles are inaccessible because of car crashing
in the case of head-ons the car is just on that tile so its simple
but for same-tile collisions its kind of on 2...
as shown in the video above i cant just do it where the same-tile crash makes just the tile where they collided inaccessible, because then another decoy coming up to that point would crash the tile behind, etc etc
the reason i cant do it is because then all the "inaccessible" tiles would be on the front half of the car, not caring about the back
if that were the case, the final decoy that crashes as shown here should be able to ride on the swapped track but it instead crashes
i think what ill do is make the back half of the car inaccessible, and then the initial crash tile is also inaccessible
that should likely work
ok, after some testing with all the same-tile stuff:
cars that collide at the same tile dont trigger switches, so it must mean same-tile collision is before gate detection
the reason i had to put it after is because on 7-3 it rams into the boundary of the level, in which case i crashed the car before it even hit the boundary, but setting the position where it crashed at the boundary
its kinda complicated but it made me have to put the decoy crashing after switches
i think i can make it only crash it on the movement where its actually trying to go into the wall though
that way i should be able to move the decoy crashing before gates (and switches), so that same-tile collisions dont trigger switches
ok... to do same-tile collisions they absolutely need to be put after generation/movements
since when they happen for decoys i need to make the tile "behind" the car inaccessible, i need the previous car's position 1 game movement ago to mark that tile inaccessible
actually i could just get the position ahead for each car before generation using math and id still have the previous car because its an unchangeable parameter passed through generation
crashing is going to have to be after gates/switches and right before movement generation though in that case
nvm that doesnt work because a car only chooses to crash itself after the collision detection is done
so a decoy can bypass a collision by appearing that its going to move ahead the next movement, but it could crash itself and not move if it decides to
thus collision needs to be after it in case the car crashes itself
mmmm thats the reason i put it before movement actually because then i wouldnt need to account for all the branches
the problem is to properly mark which tiles are inaccessible i need both the previous car's position and the current car's position
its impossible to do it at the start because you cant tell where the previous car was thanks to 3-ways redirecting you in the same direction for 2 ways
i could add a parameter thats passed through generation with the previous car but thats annoying
actually no way because then id also have to do crasrhed decoys accounting for multiple pos aheads
i think ill have to just add the previous car positions to be passed through generation
making 12 variables passed through ๐
the biggest it gets should hopefully be 13 once i add semaphores
no actually i dont think that will work either
if i go through the entire process of moving every car and THEN crash them, i need the previous stuff because im essentially going back a game movement
so if there was a train of cars following behind each other and one of them crashed not all of them would crash because it checks the cars one at a time and its adding new inaccessible tiles to that list while going over it
basically if a car crashed and THEN added itself to the inaccessible tiles cars that were tested before ignore that inaccessible tile
i think the only solution is putting same-tile collisions into the movement loop
i will see if i can make it faster
reference before i change it to being in the loop
so annoying
i cant put the same-tile collision after the branch starts (like testing each 0, 1, 5, 6 track individually next game movement) because then its doing the crash detection after everything from the previous game movement has been finalized and checked and its slower overall
so i have to deal with there being multiple different car positions because the decoys can crash themselves
๐ฅฒ
since i need to have 2 variants of the collision detection its difficult as i only want to perform a collision detection once, and as early as possible at that so it doesnt waste resources on checking stuff when a collision would be more important
i cant use the loop that confirms placable tracks because for a decoy itd look like (0, 1, 5, 6) meaning itd check for the no tile placed collision once, but check the other type 3 times
also thats later into the script than would be optimal to save time if i put it before like track picking
hm
i can make it so when a decoy is picking tiles it checks if not moving would cause any problems on second thought
i feel like other cars crashing into the decoy itself should make that impossible though
ugh the same goes for head-on crashing now that i think about it too
actually what am i saying
if a decoy is placing nothing that means its going to crash
yea, that one breaks the level since you don't need the yellow car
I'll think about what to do about it, thanks for spotting it ๐
forgot to check for collisions with stalled cars because the new collision system is inside the loop... woops
probably also goes for station stalled cars and a lot others too...
the reason why other cars dont detect theyre crashing with the stalled one is because when checking for same-tile collisions cars only check for collisions with previous cars that have generated (for example car 3 would only check for collisions with cars 2 and 1 because they have moved already)
which works because it essentially just creates the combinations to cross-check if each car works
but if car 2 is stalled and car 1 tries to ride into that tile it doesnt check for it because car 2 skipped the loop as it was stalled and car 1 only checked for no cars to collide with
instead of doing a list to make things easier im just going to create a function with the crash testing so i dont have to write it in there 9 different times
actually ill try making a list with list comprehension
ok.. with how i put it in i thought i made it so decoys cant crash with cars but i guess they can so i shall fix that
before it was ordered that decoys would be done last so i could just check if it was a decoy that crashed with the unnamed car and it had to be a decoy because they were done after hte other cars
but now its the other way around where they check backwards so it cant work
cause the decoy checks original cars now too meaning i need an indicator for if its a car or a decoy its crashing with
so close yet so far
it doesnt place tracks sometimes now fsr
ok its because decoys place 0s on top of cars that place stuff there
for example a car could place a straight track in front of it while a decoy 2 tiles ahead places nothing, overwriting that straight track and making it look incorrect
gonna try just doing it in reverse
i think its fixed but running 7-5a for a while is showing no results.. all other levels in the game work fine
im skeptical because it didnt even find any solutions.. but
ok nvm
i originally ran it with a minimum tracks of -1 which goes for any level to solve it
but i set it to 5 instead so then it can find the solution with 6 extra tracks according to the guide and run faster knowing the limit is 6, didnt find anything
sigh
set it to 4 and it found one with 5 (it doesnt work)
ok finally found out why it doesnt work
the ONE crash i didnt fix for decoys is if the permanent tile in front of it crashes it ๐
gonna make it so they can do that and i should finally be done
finally got it so it considers the best solution viable..
after all of that the last thing i had to add was making it so if the decoys crashed before the 2 movements after the last car reaches the train the solution still counted
still doesnt find the right solution though...
ok, the next biggest problem for 7-5a now is that decoys can place 0's over any tile they want (including permanent) which messes things up so much
the reason why it can do it at all in the first place is because how creating new boards from the chosen tracks work is placing them over each other
normally itd work because a board replaces all the tiles for the 1st branch it creates, overwrites all of those tracks with the 2nd branch, 3rd, etc.
but when it places nothing its not overwriting anything which becomes a problem
if multiple cars placed tracks on the same tile it wouldnt end up working because theyd end up inevitably crashing as both are going the same direction 1 tile away from each other
decoys can do that though
the method i do now though is much better because instead of making like 8 copies of the board and then modifying them i only have to make 1 and then overwrite stuff
actually it makes 8 copies anyways because it needs to pass copies through generation
so i could copy and then place tracks versus overwriting tracks and then placing
in which case i can actually avoid having to place anything because its not overwriting
it can create the 7-5A best solution if you make it the only possible path to make (basically covering every unused tile with fences) but it still doesnt generate it if you do the level normally
will try making certain tiles accessible until something pops up
for reference, here's the best solution, and where the fences would be on the hypothetical board i tested that can only result in the best solution
after some testing, removing either of these 2 fences results in the solution not being found, but it can generate the solution otherwise
curious as to why they're at the exit points but only 2 of them?
it doesnt make the 3-way at the end if one of the fences isnt there
finally figured it out ๐คฆ
its another problem with decoys being able to crash or not and whatever
the solution doesnt work because the amount of available tracks arent correctly processed
i process it properly when i move onto the next generation but not when i move onto the next car
so it can be misrepresented
as a result, in this case, the program thought it had less tracks than it did
so it killed the branch prematurely
what i did originally was negate the tracks if the list had both the possibility of placing and crashing the decoy, and then making up for it the next generation by adding a track if it was going to crash (because it didnt place anything)
so what im going to do instead is the opposite which is not negate a track but the next generation if it places a track it negates it there
that way it shouldnt conflict
ok.. it FINALLY found it but...
and i set the lowest tracks to 5
meaning any boards under that got killed
i set it to 4 and it took 60s and about 2.6m iterations
๐ฌ
it works so im not complaining
gonna test world 7 in full now (with -1 lowest tracks so it works...) hopefully all goes well
very doubtful it took 52m41s
will investigate if any levels take longer than this
besides that, the rest of the world 7 levels worked as intended ๐
took 54m15s overall
gonna work on fixing the one issue with 7-3B now and crashing before gates and whatever, i pray it doesnt take too long
actually it makes some form of sense to me now that i think about it because the heatmap limit is 10 from having the swapping track in the bottom right so it has to loop the car around 10 times before it crashes, also taking into account all of the decoy shenanigans
still absurdly long
actually i just realized that the board isnt accurate
theres a vertical track in front of the ending track instead of a 3-way which should be impossible
sigh
fixing time
fixed 
14 (the 3-way) is now in front of the ending track as intended
the only other problem is i ran 7-8 and it said it saved a track when it didnt (the solution is the same though so no worries) probably just some oversight with me changing the decoy branch available tracks so it negates after generation instead of during
yup (kind of) just forgot to remove a variable from a list when cars finish
re-did all of the world 7 levels and they worked 
all thats left to do is fix the 7-3B thing with crash priority and then i can move onto world 8
coming back to this...
simply moved where the switch code was from before generation to after generation
and that seemed to fix it
thus crashes are detected before switches
im gonna run it through world 3 and 6 just to confirm it works properly though
yeah nope
sigh
so the order i put it in works as intended, but i think i just need to rearrange some variables like stalled and stuff to make it work properly
there might be some aspects of switches that are before and after but i have to look through the whole thing more in depth
ACTUALLY
i just realized something thatd make things way easier
instead of changing literally everything so it works...
variables baby
i am going to see if i can add some variable indicating when a gate is lifted and crashes will work slightly differently on that frame to account for it
i have a list of stalled_cars that is added to the cars to check for when crashing
its updated after gates are done so i can just put it before and everything should work
im so smart oh my god
yeah thats literally all i had to do
tested 7-3b and it worked perfectly, tested worlds 3 and 6 and they worked perfectly
hallelujah we're going to world 8
Railbound Solver [Python Script] World 8/12
alllrighty
the main problem with world 8 is going to be time unfortunately
4 cars means exponentially more time
my program is still insanely fast though so it shouldnt be too much
im going to put the program onto my pc and run everything on there so its max speed
hopefully no problems arise, and if they do i pray that its just an input problem with setting the wrong values for the level like the board or cars
at least none of the world 8 levels have decoys
progress update!
things of note:
8-4a has the highest time and iterations yet, at 3h47m17s and 797 million iterations
8-5b supposedly has a solution with 7 remaining tracks
8-6a has been running for over 8 hours now with no solutions found
the program has run for about 23 hours and is only at 8-6a
im gonna check all of the better solutions and then start working on world 9 while i wait for world 8 to finish
i am very surprised world 8-6a has been running for so long
it has 48 tracks though
im basically running a sandbox level.. (which isnt too far off because thats what world 8 used to be... lol)
having the switch rail set the heatmap limit to 10 probably doesnt help a whole ton either
im afraid i cant compare things to the guide any more because most world 8 levels are outdated from when it was made soo.. ill start searching the server for best solutions ๐
on 8-3a i put a tile in the incorrect place so ill have to fix that on a re-run
i really like 8-4a's solution
its so cool to think it spent 4 hours making it and it got it with 4 extra tracks
i love thinking about how long it took to do that massive board
this 8-5b solution is so friggin cool
i love that it got SEVEN tracks remaining
its so cool to see it do this amazing stuff and it actually works after all the debugging ive had to do it makes me so happy
i cannot stress enough how cool this is
yeah all the saved track solutions work
i love this program so much dear god
so now i just gotta wait for 8-6a and the rest to finish
im kind of excited to see 8-6a be in the billions 
well i guess ill get started on world 9 with that
gotta add all the levels into my solver first though
finished adding all of world 9 and world 10
had to solve some of the levels to unlock every level so i could map it and something hit me with the semaphores
there can also be solutions that may use all tracks but have less semaphores
technically that counts towards minimum more so 
lowest tracks then lowest semaphores will be the best option
ok! getting started with semaphores im gonna have to figure out how they work in the first place
i can just add an extra level variable to tell how many semaphores the player has and then i can add another one that retains through generation
as for how they work: semaphores act as closed gates until a car passes in front of that semaphore
i can figure out what "in front of the semaphore" means once i establish the last criteria:
i need to find out where semaphores can be placed
at first glance it seems kinda random with turns and stuff but now that i look more at it it seems like semaphores can be placed at the edges of 3-ways
additionally they cant be placed on 3-ways
yeah i think thats it
semaphores are placed on the surrounding tiles of 3-ways if that tile is not a 3-way or already has an interactible on it
from what it looks like
and opening them is actually triggered by PASSING the semaphore
the next issue is figuring out what tiles are beside that semaphore however
actually i need to figure out how to know what 3 tiles are around a 3-way in the first place
instead of checking every angle the car car go into a 3-way from im just going to make a new list that tells what tiles adjacent to a 3-way can have a semaphore on them
and then i can check those 3 tiles for exceptions like having interactibles or having a car or being a 3-way
i could do the same thing to find the 2 adjacent tiles for a semaphore too but thatd be kinda lengthy and start to stop being worth it
for the semaphore's 2 adjacent tiles all those rules above apply as well as it cant be a track the car couldnt access
cause the car has to be able to ride through the semaphore fully without crashing
i think i might just end up having to make a list for all 14 different tracks
ah well
the biggest problem is figuring out how im going to generate semaphores
a car can't prematurely place a semaphore unless it places a 3-way the next frame
also placing semaphores during generation kinda breaks how it works overall
my generation system works exactly like the game as it is now, just doing it frame-by-frame
if it places semaphores during generation that'd be like placing a semaphore on frame 5 or something
but in the game semaphores are always placed on the first frame
this is going to be a massive problem
semaphores might be even worse than the decoys and i thought the decoys were the hardest part of this entire project
hold on
no. it can be done
i can check if a car has passed any tiles next to where the car wants to place the semaphore by checking the heat maps
so that solves the frame problem, i can just add an additional restriction saying adjacent tiles must have a total heat map value of 0 from cars passing them
but ill still need to figure out all the adjacent passing and opening stuff
for placing semaphores i have a variable that says whether or not a 3-way can be placed 2 tiles ahead so i can also use that
if a car is going on a straight track and it can place a 3-way 2 tracks ahead and it wants to place a semaphore then it can do that
im gonna start making semaphores work level-by-level
on 9-1 i just need to make it so if theres a 3-way 2 tiles ahead a car can choose to place a semaphore
and all the heatmap shenanigans too
actually starting with 9-2 is smarter
ughghg i just realized something
assume the cars are here during generation
the 2nd car wants to place a semaphore in front of it for the solution
so it would have to place the semaphore and track next frame
however, to place a semaphore it needs to be adjacent to a 3-way
and my generation cant create a 3-way unless a 2nd car rides over previously placed tracks
so basically, to create the 3-way the 2nd car needs to cut through here into the 1st car's path
however, the solution requires that the semaphore is placed previously
but the solution also requires the 3-way
the 2nd car cant detect any 3-way to place the semaphore because the 1st car isnt there yet
so placing semaphores based on 3-ways is out of the question now
i need to be able to place them ignoring that rule but still apply it so it follows game logic
what i could do is make cars kinda like decoys where they can place a semaphore whenever (essentially chose to stall themselves whenever) but thatd be increasing the iterations counter a bunch and making a ton of useless iterations
i dont think theres any other solution though
ok, i have an idea i think
its not exactly ideal but its the best thing i can think of right now
a car can choose to place a semaphore with the track its going to place but it ALSO places a 3-way 2 tiles ahead of that semaphore
and it does a bunch of checks along with it to make sure the 3-way isnt useless etc etc
it still wastes a bunch of iterations but its the best thing i can think of
the biggest problem is going to be i can now let cars do the same thing as decoys where they can choose to stall themselves
which messes up with crashing so much
yeah this might be worse than the decoys
there are 2 ways i can go about semaphore generation:
- place a random track AND a semaphore, then place a random track after and require the solved board have that tile be a 3-way
- place a random track AND a semaphore, then place a random 3-way after and require the solved board to have all sides of the 3-way be used
i like #1 more because it prevents the semaphore car from creating a useless 3-way that isnt playable, and it makes the whole pathway process simpler over all
i think ill try that
ill have to pass a few more variables through generation though (making it 13+ now...)
as for how the semaphore branching works... i need to incorporate it into the track selection branching somehow (ex. right now a track selection could be (2, 7, 8), so i need to be able to make it (2, s2, 7, s7, 8, s8) where the "s" adds a semaphore to that track)
i cant have any "s" in the actual number though the list would literally have to be (2, 2, 7, 7, 8, 8) so ill need an extra thing indicating which ones are a semaphore option
although honestly itll look more like (2, 7, 8, 2, 7, 8) because im gonna make semaphores get chosen last for time priority
doing the whole process first thing every frame would be looong
one of the other different things is semaphores are an interactible, not a track so i need to simply change that in the track placing process
as for how semaphores will get treated im just going to make it another interaction index and while that number is on the board it acts as a gate, but if a car passes by it to remove it it turns into a deactivated version of a semaphore with a different interaction index
i COULD simply remove them but the problem with that is tracks with semaphores on them arent allowed to become 3-ways
so just making it a "deactivated" index indicates there is a semaphore on there so i can make sure cars arent able to place 3-ways on them
i think pycharm crashed on my pc
that is very not good
according to my brother it ran out of memory which is a huge problem
im gonna run all the other levels and then try 8-6a again
here's the rest of the world 8 levels besides 8-6a
i love that theres another one with 5+ extras (6 on 8-8a)
an intruiging thing about the 8-8a solution is that it doesnt require the tunnels which probably counts for luke's broken level critera but i dont think it matters as theyre working on the new game right now
im gonna re-check 8-6a to make absolute sure its entered right and then try generating it again
yeah no its entered fine the tracks and board size are just horrendous
im gonna try making the solver place turn tracks before straight tracks
so it doesnt take forever
hopefully it doesnt crash and finishes by tomorrow..
it has been 11 hours and still no solution
im gonna look at the solution and think of what the most optimal track selection order is then put that in and try once more
ok, put the solution into a way the board can read it
going to make another program or just use my brain to figure out the optimal track order for each direction
on a side note i tested it and yes it works so generation is the problem
yeah nvm the way i had it originally is still ideal
straight then either turn
too hard to think about what the best route would be
eventually i want to convert the whole solver into c++ but i want to do that at the very end when im done with everything
because c++ is waaaaay faster
but im not as knowledged in it and if i know the python one works fine and the c++ doesnt i know its an input problem and i dont have to debug it as much
oh! i know what i can do
heatmap limit
the max should be 3 for 8-6A because the switch track is right at the end
it can only pass through it 3 times at max to make the solution possible
i dont really know how to explain it but it just works
theres no reason why it would be over im pretty sure
4 technically
3 is the max, 4 is the limit
im gonna start generating it again with a heatmap limit of 4
actually it could be 5 or 6
meh
will try those if 4 works
oh actually i still have to figure out the whole heatmap thing
will run world 6 and look at some statistics
the world 6 levels arent very insightful so i think im going to make some custom levels and analyze stuff
yeah i have no idea
the custom levels cant be big because having heatmap limits be the goal factor isnt as good as tracks
tracks can restrict the generator, heatmap limit cant
alright
8-6a still hasnt finished its been 2 days i think
my pc hasnt crashed yet though which is most of what i care about
as for semaphores, i need to do the following things to implement them:
make passing switch the interaction index โ
add extra numbers for the track generation to implement semaphores in the next generation based on number
make semaphores stall cars correctly โ
figure out how to detect passing โ
properly make the combinations for semaphores
im gonna work on stalling and passing first
ill start with 9-1 but with the semaphore already placed
for passing the most important things is what tiles and what directions need to happen for a semaphore to flip
im gonna do what i said before and just make a massive list that indicates what tiles adjacent to the semaphore and what directions can happen for a flip
actually
the position of the tile adjacent to the semaphore indicates what the passing direction are
because if a semaphore can be placed to the right of a tile that means it will ALWAYS be passing up/down
same with left
that makes this way easier
yesss
this is with the semaphore pre-placed but the fact that it can handle processing them now is good
just gotta make it able to generate now is the 2nd half
what i can do is not add anything to the track combos and then just split the final track adding before the next generation into 2 parts where it adds a semaphore for every possible track or doesnt
that would work
however there can be more than 1 semaphore on some levels in which case it might want to place 2 on the same frame
oh ok ok
what i can do is for every track combination that wants to be used for the next generation
is then add ANOTHER semaphore combination onto that that determines which tracks can have semaphores for the next gen
i need multiple semaphore combinations for every track combination though
so just a little bit more effort
im gonna try and make semaphore stuff done absolutely last
idk how much of an issue itll be but we'll see
i dont think theres any way i can use itertools to get an effective combination i want
because for the semaphore stuff lets assume i have 3 cars and 1 semaphore. a possible semaphore combo could be (False, False, True)
I could either: do False, True into itertools but that wont work because if i did any that allow duplicates to make that combination happen i'd also need to allow true to have duplicates. but since we only have 1 semaphore, it can't, which doesnt work with that method
or I could do False(1), False(2), True into itertools but that also wont work because then the combo could create duplicates like False(1) False(2) True and False(2) False(1) True
if i do it without itertools its gonna be way more time consuming and this is a process that needs to be done for every single iteration
ok i think i know a workaround actually thatll work
i can start with a (False, False, False) empty list at the start each time and THEN do a permutation to add the true values
for example the Trues would be ([None], 0, 1, 2) here which i can make happen
or if i had 3 cars and 2 semaphores itd be (False, False, False,) and (None, (0), (1), (2), (0, 1), (0, 2), (1, 2))
the single and double semaphores in one move might be a problem though
theres no feasible solution for that other than just doing it multiple times with differing lengths
technically i could do (0, 0) and (1, 1) etc in place of it to make it 1
because they just overwrite each other
i think ill do that
its been 4 or 5 days since i started generating 8-6a and it crashed on me just now
so i dont think its going to get solved
...yet
ill come back to it later
tried making semaphore gen happen right as everything is getting passed on but i dont think itll work great
id have to use some more loops and make my own(ish) combination system
plus i need to change the cars position because all the stuff to move them has been done already and id have to change the cars twice before doing generation
so overall its a time waster so ill end up having to put semaphores inside of generation
ok, i think the semaphore 3-way thing isnt going to be needed because the program inadvertently requires it to happen
if a car places a semaphore, a car HAS to pass in the tile in front of the semaphore to trigger it
and if that happens, one of the cars is going to end up making a semaphore because the cars cant go in the exact same direction when the semaphore is triggered
so 3-ways happen none-the-less
thus the only requirement i need is making it so if its already a tile with an interactible on it or if the tile ahead of the semaphore is permanent and not a 3-way because in that case its literally impossible for that semaphore to exist
also, just to simplify things i might just make 6 more tracks that are the exact same as base but new numbers indicating it also wants to place a semaphore
although if i do that i have to copy and paste all the 6 tracks' direction instructions which is wasteful at the same time
ohh i know what i can do
i can split the list in half because for every usable track there'll be a semaphore copy
actually no that still wont work because i need a special indicator for the track that says whether or not to place a semaphore (during generation)
so the 6 base tracks is actually my best bet
when i read the track number to place it i can just negate it by 20 or whatever to make it equal the correct track
so yeah 6 extras will actually work
the only problem with this whole thing is if i had 2 cars and 1 semaphore i need to prevent any combinations that let both cars place semaphores
i cant do that inside of the function so i either have to make my own or skip the ones that arent valid
additionally i have to make it so they barnch off and dont move including dealing with crashing etc
although i dont think crashing will be a problem at all because if a car is going to crash theres no point in placing a semaphore
its going to be even more of a problem with decoys though
im gonna make it so if a car is ever facing a semaphore without placing one then it kills that branch because its impossible for that semaphore to open and that car will get stalled indefinitely regardless
i dont think theres any point in decoys doing it either
actually no there is
it extends like the crash distance for decoys if that makes sense
so if a level had 3 decoys and 2 are facing a semaphore it extends the crash zone so the 3rd decoy might crash where it wouldnt have previously
ill deal with decoys in world 10
world 9 doesnt have any
ok, i implemented some stuff so it should work now, but it wasnt working cause it triggered the heatmap limit
basically it added to heatmap, placed semaphore, ... , semaphore opened, added to heatmap again
normally it works for gates cause it stalls the car and then skips the heatmap, but then the gate is opened and it only adds 1 to heatmap
im not gonna create an additional thing to make different heatmap branches with 1 less on the semaphore ones
so instead i can just not add the 2nd heatmap val if its coming from an opened semaphore
only issue with that is theres no way to detect if its coming straight from an opened semaphore or if its just passing through an open semaphore
so instead actually when it changes the semaphore to open i think ill pre-emptively negate 1 from the heatmap counter so that way when it adds 1 on the 2nd time its a net 0 increase
will do that
yesss
it still doesnt really work properly but it can solve 9-1 without any assistance
i still need to:
- semaphores cant place more than they have โ
- semaphore placements must be legitimate (for permanent)
- deactivated semaphores can't be made into 3-ways
- semaphores can't be placed if a car has previously crossed, basically making the semaphore useless โ
but im glad it can solve a level
(it also works on 9-2)
oh! i actually just realized it needs to be indicated where semaphores are
showing the interactions board probably isnt pretty so ill need some way to put it on there nicely
i just realized i can maybe use coloring for when i print the final board so for aesthetics i might color stuff to look more like the map
included with that i can color code semaphores something specific
cant color numpy arrays without graphing them literally so when i do that eventually ill incorporate it
so instead for now ill just have a thing beside it saying the coordinates and the tile number its on for convenience
oh and since I need to indicate those semaphore positions i also need a best_ints along with the best_board lol
i think thisll do for now
for now with extra semaphores i think ill just skip the combo if it has more-than-the-available semaphores but its a huge waste of resources
will see what i can do to improve it later
ok! there are no more semaphores appearing out of thin air in the progarm so its legitimate for now
so 1 requirement is finished
i made some adjustments so now gates open properly and it looks like the semaphores are already coming together nicely
it can place them and solve levels up to 9-6
though it found an invalid solution on 9-2A so i have to fix that but
the fact that it can solve some of the boards now is exciting
also, on the best semaphore count thing i think im going to pass on it for now
because allowing the program to work with 1 extra track given the option not to makes it run a lot slower cause it can process more (for the most part usless) iterations
ill probably run the whole program and figure out the minimum tracks for each level then see after that if theres any better semaphore solution
oh the reason 9-2a found an invalid one is because i didnt make it so placing semaphores also checks if they are being previously activated and therefore useless
i can fix that i think
Do you have the code somewhere on GitHub?
I was thinking about creating a solver myself, but Iโve just noticed that you had one almost ready. Iโm curious how you approached solving the levels. Iโd love to see the code if you make it public at some point.
i think i posted a version of the old code a while back but its a completely different gen method
i can repost it
the new code
as for solving the levels i use recursive generation and just create every possible PLAYABLE board and then it tries them until it finds a solution
Are you planning on solving all the levels?
and i have an extremely tight list of requirements for a generation to continue branching
yes
im at world 9 right now, if i get into the mood again of coding this next month probably then i should be able to finish it
Why are working on it? It seems like a lot of work?
the only level i havent solved past world 8 is 8-6a because it took 4 days and my pc didnt generate it because pycharm crashed
im saving it for c++
just for fun lol
i like coding as a hobby
ive been working on this for like 8 months now i think
7?
7
Are you a professional programmer?
Good job then!

i can go more in-depth about how the program works at a later time itd take like 30 mins
I wonder why the Afterburner folks havenโt created a tool like this for themselves. It seems like it would save hours of time when designing new levels. Itโs also not that hard when you have some experience with similar solvers.
honestly i think itd seem insane if they made a solver
given it took me 7 months to get this far
well even if they have better experience
maybe 3 months...
i guess they know the inner workings of the game better too but thatd still be a month or 2
- they have to maintain it when they add mechanics
And they could be working full time on it. I bet you donโt spend 40h/week on your script.
in all honesty i probably was at around 30h/week when i was making it
other people play video games with their free time but id usually work on this
Wow ๐ฒ
~25 actually but still
but yeah youre right
they have a team too
would you rather spend resources making a solver for a month or continue developing and fixing a new game
its not a necessity anyhow
would be cool tho.
I wonder how much time it took to design the levels manually when every new idea had to be tested whether it was solvable in the first place. They must have rejected many more levels than they put in the game.
well, its a puzzle game
im sure they develop a cool solution or some wacky board and then start with that, and tinker the level until their solution is the only viable one
but yes many were probably rejected
Iโll ask them in the dev channel.
ah wait
concerned about making a solver i think i asked luke once or he commented on it
or mirzka i cant remember
i can try and find the message but i think they said itd be too hard to maintain for the main point
thats a suited question nvm
I donโt think it would be that hard to adjust the solver to new mechanics. You can probably vouch for it since you added them one by one.
Haha ohhhhh nonono
the mechanics are what makes this solver so hard
i got the main game movement and track placement in a month or less
i had to remake the solver once for world 5
and twice more for world 6
How do you represent a level in Python?
let me get my laptop
i can go on for 30 minutes about how this works
concerning levels, i have multiple arrays of numbers for the data of things in levels
i use numpy arrays btw
as for boards, i have a number indicating each track type
then the program does what it will with that number (track)
So you map sth like 1 to a straight track, 2 to a curved one, etc.?
heres an example of 6-9d in the program
these are the cars (they get converted to numpy arrays during gen i think)
and then i also have an interactibles board for things like tunnels and switching tracks
Did you write unit tests to check whether the solver was still working after a new iteration?
cause itd be dumb to have to make like 15 copies of each track for different gates
what is a unit test?
and then these are the interactible indices and board indices respectively
concerning the numbers for the board theyre on the right side i can talk about the rest of the numbers later
A piece of code that runs some part of your code and then makes some assertions, e.g. tries to solve level 5-5 and asserts that a given solution is found.
yup
I could help you out with GitHub if you ever want to put your code there. Itโs pretty straightforward.
ill do that once im done with the project, thanks ๐
i can post what i have here if youd like
Iโll follow this thread and wait for the final version.
tysm
Are you planning on describing your work on a blog or somewhere? Iโd read it.
yes!
once im done with the whole project i want to make a youtube video on it
i started a script for world 1 a while back
i can explain it if you want, itll take a bit
I think I get the idea already.
Good luck with finishing the project! Iโll be waiting for your updates.
I found this solver in Java on GitHub:
world 1 and 2 only
Do you have a YouTube channel?
not really
i used to make roblox videos a long while back and i havent really made anything new
anyways.
now back to semaphores, i still have to add the thing where it checks if placing a semaphore isnt useless/invalid
the only ways a semaphore can be invalid when placed is: a car has traveled adjacent to the semaphore, triggering it
since i have the list indicating the 2 triggering sides i just need to use that to check if there's any heatmap values on those sides
theres one problem however.
for some reason semaphores arent opened if they're right behind a starting car
i think im thinking too far ahead and its messing me up im just gonna add in the limitation so i can work with this better
for finding if the cars have passed the semaphore at all i just need to negate the total car visits there by 1 because the car placing the semaphore is technically adjacent to it and has a value of 1
sigh
i have all the stuff to check adjacent tiles but for the semaphore to actually trigger properly i need to change stalling
because if a car places a semaphore, the frame it places the semaphore it isnt yet stalled
however, the next frame it isnt marked as stalled until after all the movement is done
the first frame the semaphore and 3-way is placed (NOT THE VERTICAL TRACK, its there so the semaphore can be placed)
car 2 is not technically stalled
the next frame, car 1 is facing downwards on top of the 3-way
semaphores are checked to be deactivated before the stalled stuff is added
so since on frame 2, when it checks for if adjacent semaphores should be activated, it doesnt do it because car 2 isnt technically stalled yet
yeah ok
im just gonna make it so cars get stalled immediately after placing a semaphore
that should be good?
idk if there could be any instances where multiple cars swap their stalled state like [False, True] to [True, False] that throw the program off
i know i fixed that for gates but ill do it for semaphores and hope for the best
will see in later worlds
YES!
instead of changing the stalled after generation and having to deal with different car position branches i just made it so there needs to be a semaphore in front of the car
cause if there's a semaphore its stalled anyways
sweet
now the levels up to 9-6 are solved
nvm 9-6 also works i just forgot to make the tunnels face the right way in the level.. 
its still generating 9-11 (which makes sense because its a larger level) and some levels didnt work properly
i dont think you can place a semaphore on a 3-way
also that track count is misrepresented
so it's placing invalid semaphores on 3-ways is the only issue i can think of now
just have these 2 things left to do
it found a legitimate 9-10B solution with 2 extra tracks which is pretty cool
im gonna fix the semaphores and then it should be good
i can make it so semaphores cant place on permanent tiles with interactibles very easily
the 3-way thing is only slightly more challenging because a car can place a semaphore on the same frame another car makes that tile the semaphore will be placed on into a 3way
but i can just check it after generation is done once the semaphore actually gets placed during the final generation branching
wait no im stupid
that cant happen because 3-ways can only be placed on already placed tracks
cant be done on the same frame as another track getting placed cause its not technically there
oh i also have to add a new interaction index indicating where the starting tiles of cars are
because semaphores cant be placed on tiles with interaction indices on them
so thats just a more convenient way of not allowing them to be placed there
nvm that isnt needed because those tiles will always have a heatmap value of 1+ from the cars being on them, and semaphores cant be placed on tiles with any heat
all the levels up to 9-8 work now, 9-8 is now not finding a solution for some reason
the problem comes from not being able to place the semaphore... the program cant complete the level even if all the tracks are placed in the right order, but if you force it to place there then it works
i think i see now
a car can get onto a switch tile as seen here, and then choose to place a semaphore
again, the semaphore doesnt stall instantly so it triggers the switch a 2nd time when it places the semaphore
ill make it so it instantly stalls now
2 cases of it being needed is enough
just gotta add 2 lines
yup!
9-8A also doesnt work unless you specify the semaphore is there during level setup
the cars refuse to place it
..oh
๐ฌ
its behind another car
so i finally have to deal with the thing i mentioned earlier i forgot about
it cant place the semaphore because that track under the 3rd car has a heatmap of 1 from being there on the first game movement
but the game is goofy and doesnt register semaphore closings on the first game movement
one thing i could technically do is just make it so when generation recursively calls itself it has an extra false variable but when i start the entire generation from the first function its true
and then read that variable to check whether or not semaphores can do anything the first frame
the only weird thing would be if someone were to make a custom level with a car starting on a 3-way in which case it should maybe trigger it because it could approach from the side but the vanilla game doesnt do that so i cant tes it
actually i forgot how my program works lol
in the game semaphores exist on the first frame, in my program they're placed during generation
adding the 27th index to excuse a tile's heat or just excusing a tile's heat at all isnt the way to go
because a 2nd car could come down and still trigger it
i can just check if the heat is above 1 nvm
yeah that should work
i made it only check the opposing side for the behind-the-car semaphore because if a car, on the first frame, placing a semaphore behind another car then both sides would be starting cars
the problem with that is if theres a starting car track i want to negate 1 because it technically shouldnt count
...but if the car that wants to place the semaphore IS a starting car, it still has a value of 1
and i negate another 1 for the car itself because it also gets checked
i cant allow for a total value check for semaphores to be -1 OR 0 because theres a possibility all that happens, it gets -1 partially, and then some other car visited a tile twice and it magically turns into a 0 which is still valid when it shouldnt be
for a semaphore to be placed, the total surrounding heatmap value (the total heatmap vals of every direction on both tiles adjacent to the semaphore) needs to be 1, and then negate by 1 to make 0 as the car placing the semaphore will always give a heatmap value of 1 for existing adjacent to the semaphore when placing it
if theres a first-frame car tile, then it needs to be excused and negate another 1 from the counter because the surrounding heatmap should then be 2
if the placing car is on its first frame, it will still have a heatmap value of 1 and negating by 2 makes that -1
to make things simpler i could technically change the index to like a "semaphore can be placed here because its behind a car" thing and then put it on those tiles behind cars
but thatd be incredibly inconvenient to make, first of all, and if people wanted to make custom levels itd be even more challenging
actually i could automate it when the program starts and just add it in during the program instead of setup ๐ค
if thats the case though then the semaphore needs to be able to place on 27 indices in addition to 0
if 2 cars are facing with their backs to each other with a 1 car gap like on world 8 then thats pointless because id need to indicate to negate 2 heatmap values since theres 2 starting tracks there
no ive got it
ok
instead of adding the values to the interactions board im gonna have them in a separate list i can just look at
itll just have the original starting position of every car
if the car placing the semaphore is on its original starting position, it doesnt negate 1
otherwise it does
and then i can negate all the other starting tiles around the semaphore
i can just use the original car data
yes i think this should work
yup it managed to place the semaphore with the given solution
just have to automate the starting indices being added
yesssss
it solved 9-8a on its own
couldve taken less time had i closed some stuff but meh
i hope everything else works
the only thing im worried about is im pretty sure the massive amounts of variables i added to calculate if placing a semaphore is valid is taking wayyy more time
ill probably try to simplify stuff later
its slower somehow
the speed is faster because i closed some stuff but the iterations is higher
๐ฅฒ
its not too bad for now i guess
back to seeing if world 9 works...
aaaand it placed on a switch for 9-10
forgot to put parentheses around an or statement ๐คฆ
what a satisfying solve for 9-10A
9-11 has an extra track :)
9-11 took a while as is 9-11A and probably B, so im going to run it on my faster pc and start working on world 10
i now have usable semaphores, but applying any mechanic to decoys is bounds harder
alright!
theres 7 non-decoy levels in world 10 and 6 with decoys
so i think the first 7 should be fine and then ill have to deal with the last 6
10-1a is also massive so ill leave that for my pc later
9-11a worked, 9-11b failed because i forgot to put the tunnels in ๐
well thats a first
tunnels are in and im confident the board is shown exactly correct
hmmmm
dont think thats supposed to happen
sigh
since i added semaphores cars can create multiple branches
...i forgot to account for it in crashing
oh how i hate the option to be able to have multiple futures
why cant cars have a decided fate...
semaphores still dont technically stall cars instantly i think was the problem actually
yup think that fixed it
ayyy
1 track saved
world 9 is now solved 
im gonna count it for now as this far because 8-6a is a special exception... it takes too long
Railbound Solver [Python Script] World 10/12
oh yeah, heres all the solved world 9 levels
only 4 tracks saved which is pretty impressive imo considering semaphores can be placed anywhere you want
longest level only took 15 minutes which is pretty tame compared to some other stuff ๐
trying to add 10-5 in and theres one problem now
the thing about decoys looping is they dont kill themselves from the heatmap
they cant
usually that works because cars will inevitably finish and decoys wont loop forever
but if a car stalls on a gate or sempahore then it never ends because the car cant increase heatmap (doing that while stalled is stupid) and the decoy will never end the program cuz its looped
i never had this problem cause there wasnt a level where the car gets stuck on a gate and has a looping decoy
i think what ill do is if all the cars are stalled then it starts a check to see if all the decoys are also looping or invalid
that way is the shortest path i think
adding a limit to how long a car can stay stalled for isnt great because shorter vs longer loops will take that much longer
same for a higher decoy limit
i can:
- make the decoys have a heatmap limit but make it much higher than cars (10+)
- have a list that records whether or not decoys are looping
- give decoys a heatmap limit after all cars are stalled
- give decoys the looping list after all cars are stalled
the problem with the first one is that it wastes an incredible amount of resources running the loops over and over and over until it reaches the limit so thats probably not happening
the 2nd one is kinda hard to tell during the program because of switching tracks from buttons
the 3rd and 4th ones are kinda the same now that i think about it
but i feel like the best concept would be waiting for all the cars to stall and then testing the remaining decoys to see if they get back to the same position (loop)
the only problem is that still wastes resources waiting for the cars to finish looping..
im not sure what the best way to do this is without wasting resources
it needs to guarantee the decoy is looping as soon as the car is stalled but thats hard to figure out
cant try to figure it out before because cars are still in motion but if you do it after youre progressively wasting resources
i could do it beforehand easily by just checking if decoys have heatmaps above 1 but switching tracks makes that useless
i think the best bet i have right now is waiting for cars to stall and then waiting for decoys to make a full loop back to the position they were at when the car stalled
ACTUALLY
bringing all this up gives me an idea to make the program even faster overall
usually the heatmap for levels is 1 because if a car has a heatmap of 2 (it is in the same exact position twice) that means its going to proceed along the same course as before and loop
but if there are switching tracks that allow the car to be in the same exact position but not proceed along the same course then i set it to 10
which goes well because i am confident there is NO level in the game that would need a heatmap above 10
the highest i think ive ever seen is 7
this is also bad though because in the case of looping, a car has to loop 10 times on a level with that even if it doesnt ride over a switching track
so i can probably implement some method to where the heatmap limit is kinda raised every time a car passes on a switching track
but the raising cap is then 10
i think when i made world 5 waaaay back in v4 that was one of the methods i did where when the heatmap was worse i made it so it kills the branch if a car goes over a swapping track over 5 times
the only problem then is i have to format the heatmap differently
because the limit wouldnt always be 1 on a level with switching tracks to kill a car
i have to account for whatever the car was on before
actually no itll always be 1
if a car passes on a switch track how do i then determine which tracks are allowed to be above 1 though
for now ill just use the horrible solution i thought of initially of decoys having a larger heatmap
because it works for now and i can ponder on this later
albeit slow...
it works!
2 saved tracks is always a pleasant sight
so thats one semaphore decoy level down and 5 to go
theres still a lot more to be done, i know i have to make it so they cant just place semaphores without 3-ways because decoys would be able to do that and still get a solution opposed to cars
as well as allow decoys to stall together on a semaphore but that might already be done with how the code is for decoys
ill bet theres more gate stuff that isnt coded for decoys though
maybe not
i ran the solver for all the world 10 levels except 10-5A, 10-1A, and 10-2B (because those are really long) and they all worked 
im gonna run those all through my computer which can do it faster and then make some custom levels to add in the decoy gate stuff
actually i cant think of a board that would have a solution with decoys both on a semaphore
the entire solution would have to be based upon it
the biggest problem is decoys... dont really need to do that
they can just crash themselves
- if a decoy was going to place a semaphore, it would need to be on newly placed track which removes the necessity for needing a semaphore because to even have a point to having 2 decoys stuck on a semaphore a decoy needs to cause a bad solution (ex. beating a car to the train) without a semaphore, where that semaphore would stall it
it just
i cant think of a board that could possibly accomodate that and it seems extremely unlikely and not useful
i will code whatever gives me an error
im gonna try and implement the new heatmap system with swapping tracks and figure it out before i move onto world 11
the main problem with it is figuring out which tracks to excuse
i know that 3-ways are the entry and exit points of loops though
shrug
im going to implement the heatmap after all cars are stalled i guess
not ideal but it works better than what i have now
actually even that takes some effort
womp womp
i feel like implementing world 11's mechanic more right now
it should be extremely easy... i just have to make any decoy-to-car interactions also valid for the numeral cars as i will call them
luckily with how i set up decoys and cars way back in world 7 i can just make it so numeral cars are type 2
cars are type 0, decoys type 1, and numeral cars type 2
other than that i need to add a numeral train tile which will be 21
but that should be it
the most frustrating part is adding every level ๐ฅฒ
worlds 11 and 12 are massive
actually the one problem i just realized is numeral cars can have their train on both the left and right
...im going to have 2 different tile types for the trains just to make it simpler
finished adding in world 11, world 12 should take another hour
inputting numbers over and over and over is an experience...
finally finished adding world 12 
12_8b has to be the biggest level ive ever seen
12_10 is also extremely massive and it has sooo many different mechanics its insane
it literally has every single mechanic from every single world
ok, i have to add probably the last variable that retains through recursion which will be solved_ncars, pairing with solved
actually i can put the numeral cars in solved too and just have 2 lists
scrap that
adding all the stuff for cars to numeral cars is gonna be a huge pain
im gonna have to make a lot of new if statements because of the car number calculations 
nvm it wasnt too difficult
just 1 if statement added
otherwise a lot of number offsetting
ok, i think i have half of it set up but one thing is eluding me now
when a car reaches the end i remove some of its data then and there before it does the generation branching because its pointless to have it accounted in all of that
normally i can do it easily because the solved car should always be the first one in the list (cause the order is 1, 2, 3) but with numeral cars thats not always the case so i have to waste resources finding the first numeral car
...unless i think of another way
i think i can have a list of all the cars that get solved in a frame and then iterate over them to remove it
that way ill have the data for which cars to remove no matter what
yess
it can solve the pure basics at least
past 11-2 it failed
...think i forgot to make them test for collisions
actually no it should still test for them
hm
10-1a has been running for about 12 hours now
it found a solution at 3 hours in but hasnt finished yet
i pray it isnt another 8-6a incident...
ok, the problem for 11-2a is the numeral car placed a 3-way that messes up with car travel timelines (it placed a 3-way that interferes with another car's path)
so its probably just one of the things in the code i didnt account for multiple car types
the normal cars didnt add to their heatmap
thats why
i made the car_index for numeral cars apply to normal cars too
...i also made it so they can arrive at either train
should hopefully be the last fix ๐ค
i also need to make it so if a car goes to the incorrect train it counts as a failure
ok, 11-2a made me realize quite possibly the stupidest thing ive ever seen from this program
...i forgot to make the game correctly process placing 3-ways
sigh
im not sure how major of a fix thisll be but ill rerun some levels for good measure
2 things:
for 1, i made checking for if "placing" a 3-way affects another path always check even if a car is riding over the 3-way NOT for the first time (remember that cars running over tracks technically place them again)
for 2, i guess i didnt format the code correctly to properly find 3-way collisions
this is basically what the program is doing
the order of generation is normal car -> numeral car
so when the normal car places the 3-way it checks for if any cars going that way will have their paths messed up by referring to the heatmap
since the numeral car hasn't taken its turn yet (and heatmaps are added at the beginning of a turn), the tile the numeral car is on doesnt have any heatmap value to it, making the 3-way placement valid
the normal car now has a generated path where it is on the numeral car.
the numeral car then takes its turn, adding the heatmap, and then checks for same-tile collisions
it doesnt capture anything because when same-tile collisions are checked it looks to see if the position AHEAD of the car is colliding with anything generated
since the position ahead of the numeral car isnt colliding with the generated car, it continues with the program
im just going to make it so same-tile collisions also check for if any generated cars are on top of the car...
actually no that doesnt solve it
in fact that breaks the program
so i just need to make heatmaps get added all at the same time
...it shouldnt affect the program i hope
with that i finally got it to work
im not sure if what i did makes the program slightly faster or slower but it can properly solve now
gonna test some of the previous worlds to make sure nothing is awry
i find it strange that i completely forget how parts of my code work way back from worlds 5 and below when i come back to them
alright, pretty sure the heatmap change has been resolved for the whole program now(?)
all the worlds i tested worked
back to 11...
aaaand 11-2b infinitely loops
it solves it but then keeps running it after its solved 
ah
when it checks for solved cars the solved list is 2x2 (2 cars and 2 numeral cars) where there could be 2 cars and 1 numeral car so it will nnever think its solved because the "2nd numeral car" never solved but it doesnt exist
so i just need to make the list a unique shape
yesss
i love finding extra track solutions
didnt properly do stations for numeral cars but i think thats the last thing
world 11 should be finished
forgot that i made the interaction index 27 a car starting tile for semaphores ๐คฆ
made the nmeral car stations overlap with that and take indices 27-30
going to change it to 28-31 then world 11 should be done
11-9a 3 saved 