Changing fixed list of lists to dynamically generated

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Post Reply
Message
Author
Lacha
Newbie
Posts: 12
Joined: Wed Mar 06, 2024 12:23 pm
Contact:

Changing fixed list of lists to dynamically generated

#1 Post by Lacha »

Dear Renpiers,

I have a special request. I have built a game where you have to untangle traffic. Cars are placed on a map and have fixed routes to get out. If a car blocks the route, the clicked car cannot drive out. The game itself is pretty complex. I'm handling the placement of the cars and the routes they have to take by a list of lists.

Code: Select all

    def set_traffic_cars():
        global traffic_cars
        traffic_cars = [
            [1,11, "down",  "right",        [11,10],0,0,True,False],                                    #
            [4,14, "up",    "straight",     [4],0,0,True,False],                                        #
            [6,16, "up",    "straight",     [6],0,0,True,False],                                        #
            [8,18, "down",  "left",         [18,19],0,0,True,False],                                    #
            [10,11,"left",  "straight",     [10],0,0,True,False],                                       #
            [11,12,"left",  "straight",     [11,10],0,0,True,False],                                    #
            [12,13,"right", "turnright",    [13,23,22,21,20],0,0,True,False],                           #
            [13,14,"right", "left",         [14,4],0,0,True,False],                                     #
            [13,23,"down",  "right",        [23,22,21,20],0,0,True,False],                              #
            [14,15,"left",  "straight",     [14,13,12,11,10],0,0,True,False],                           #
            [15,16,"left",  "right",        [15,14,4],0,0,True,False],                                  #
            [16,17,"left",  "right",        [16,6],0,0,True,False],                                     #
            [17,18,"right", "straight",     [18,19],0,0,True,False],                                    #
            [18,19,"right", "straight",     [19],0,0,True,False],                                       #
            [20,21,"left",  "straight",     [20],0,0,True,False],                                       #
            [21,22,"left",  "turnleft",     [21,31,32,33,34,35,36,37,38,39],0,0,True,False],            #
            [21,31,"up",    "left",         [21,20],0,0,True,False],                                    #
            [22,23,"left",  "turnleft",     [22,21,31,32,33,34,35,36,37,38,39],0,0,True,False],         #
            [23,24,"left",  "straight",     [22,21,20],0,0,True,False],                                 #
            [30,31,"left",  "straight",     [30],0,0,True,False],                                       #
            [31,32,"right", "turnright",    [32,42,41,40],0,0,True,False],                              #
            [32,33,"left",  "straight",     [32,31,30],0,0,True,False],                                 #
            [32,42,"down",  "right",        [42,41,40],0,0,True,False],                                 #
            [33,34,"left",  "straight",     [33,32,31,30],0,0,True,False],                              #
            [34,35,"right", "straight",     [35,36,37,38,39],0,0,True,False],                           #
            [34,44,"up",    "left",         [34,33,32,31,30],0,0,True,False],                           #
            [35,36,"right", "turnright",    [36,37,38,48,58,57,56,55,54,53,52,51,50],0,0,True,False],   #
            [36,37,"right", "straight",     [37,38,39],0,0,True,False],                                 #
            [37,38,"right", "turnright",    [38,48,58,57,56,55,54,53,52,51,50],0,0,True,False],         #
            [38,39,"right", "straight",     [39],0,0,True,False],                                       #
            [40,41,"left",  "straight",     [40],0,0,True,False],                                       #
            [41,42,"right", "turnright",    [42,43,53,52,51,50],0,0,True,False],                        #
            [42,43,"right", "turnright",    [43,53,52,51,50],0,0,True,False],                           #
            [43,44,"left",  "turnleft",     [43,53,54,55,56,57,58,59],0,0,True,False],                  #
            [43,53,"down",  "right",        [53,52,51,50],0,0,True,False],                              #
            [44,45,"left",  "turnright",    [44,34,35,36,37,38,39],0,0,True,False],                     #
            [45,46,"left",  "turnleft",     [45,55,56,57,58,59],0,0,True,False],                        #
            [45,55,"up",    "left",         [45,44,43,42,41,40],0,0,True,False],                        #
            [46,56,"down",  "left",         [56,57,58,59],0,0,True,False],                              #
            [48,38,"up",    "right",        [38,39],0,0,True,False],                                    #
            [48,58,"up",    "right",        [48,38,39],0,0,True,False],                                 #
            [50,51,"right", "straight",     [51,52,53,54,55,56,57,58,59],0,0,True,False],               #
            [51,52,"right", "straight"      [52,53,54,55,56,57,58,59],0,0,True,False],                  #
            [52,53,"right", "right",        [53,54,64,74],0,0,True,False],                              #
            [52,62,"up",    "left",         [52,51,50],0,0,True,False],                                 #
            [53,54,"right", "right",        [54,64,74],0,0,True,False],                                 #
            [54,55,"left",  "left",         [54,64,74],0,0,True,False],                                 #
            [55,56,"left",  "left",         [55,54,64,74],0,0,True,False],                              #
            [56,57,"right", "straight",     [57,58,59],0,0,True,False],                                 #
            [57,58,"right", "straight",     [58,59],0,0,True,False],                                    #
            [58,59,"left",  "turnright",    [58,48,38,39],0,0,True,False],                              #
            [61,62,"right", "turnleft",     [62,52,51,50],0,0,True,False],                              #
            [62,63,"right", "straight",     [63,64,65,67,68,69],0,0,True,False],                        #
            [63,64,"right", "turnleft",     [64,54,53,52,51,50],0,0,True,False],                        #
            [64,74,"down",  "straight",     [74],0,0,True,False],                                       #
            [67,77,"up",    "right",        [67,68,69],0,0,True,False],                                 #
            [64,65,"left",  "turnright",    [64,54,55,56,57,58,59],0,0,True,False],                     #
            [66,65,"left",  "turnright",    [65,64,54,55,56,57,58,59],0,0,True,False],                  #
            [67,68,"right", "straight",     [68,69],0,0,True,False],                                    #
            [69,68,"right", "straight",     [69],0,0,True,False],                                       #
            [66,56,"up",    "right",        [56,57,58,59],0,0,True,False],                              #

        ]
        return traffic_cars

Each item of the first list represents a car.
The sublists have diverse indizes:
Index 0 & 1: The coordinates the car is in between.
Index 2: The direction the car faces to (left, right, up, down)
Index 3: The direction the car will drive to (straight, left, right, turnleft, turnright)
Index 4: A list if path coordinates the car has to drive along to get out of the map
Index 5 & 6: pixel coordinates of the cars (get set when the car gets placed)
Index 7: Boolean that determines if the car is visible atm. Default is True
Index 8: Boolean that determines if the car is moving atm. Default is False

The current function just returns the list of cars as a static list to reset the game.

I would like to generate a list dynamically. In my thoughts this seems to be very complex.
Cars (and their paths) must be prevented to face each other to prevent a situation where the game is unsolvable.

The coordinates of the cars are fixed and also the number of cars is a fixed value.
The map has fixed paths and endpoints to leave the map.

What do I hope to get from this post?
Ideas how to generate this list without getting conflicts.
How would you start?

Best regards

Lacha
Attachments
traffic-game2.png
(256.75 KiB) Not downloaded yet
traffic-game1.png
(247.25 KiB) Not downloaded yet

User avatar
m_from_space
Eileen-Class Veteran
Posts: 1057
Joined: Sun Feb 21, 2021 3:36 am
Contact:

Re: Changing fixed list of lists to dynamically generated

#2 Post by m_from_space »

Lacha wrote: Tue May 21, 2024 4:09 am The current function just returns the list of cars as a static list to reset the game.
Why do you return a global variable? It is already out there, no need to return it.
I would like to generate a list dynamically. In my thoughts this seems to be very complex.
Cars (and their paths) must be prevented to face each other to prevent a situation where the game is unsolvable.

The coordinates of the cars are fixed and also the number of cars is a fixed value.
The map has fixed paths and endpoints to leave the map.

What do I hope to get from this post?
Ideas how to generate this list without getting conflicts.
How would you start?
So first of all I really hate cars, but problems not so much. :P So in general it is easy to create a list (of lists) dynamically. A fixed number of cars just means using a for loop in a certain range for example. Making cars not face each other seems pretty trivial as well, by just checking the direction of neighboring cars for example. I have no answer to the question of solvability. First because I don't know anything about your game and also this might be about a complex math problem that nobody knows the answer to.

But here is the general idea:

Code: Select all

# the amount of cars
define CARS_NUM = 30

# the individual positions a car can stand at (should be at least the amount of cars)
define CARS_SPOTS = [(1, 1), (2, 1), ...]

# directions (left, right, up, down)
define CARS_DIRS = [0, 1, 2, 3]

init python:
    def get_random_list():
        carlist = []
        # make a copy of the possible spots
        spots = CARS_SPOTS.copy()
        for _ in range(CARS_NUM):
            # randomize spots
            renpy.random.shuffle(spots)
            # pick a random spot and remove it
            spot = spots.pop()
            dir = renpy.random.choice(CARS_DIRS)
            # all the stuff to determine if a direction is valid
            ...
            carlist.append([spot, dir, ..., True, False])
        return carlist

default traffic_cars = get_random_list()

Lacha
Newbie
Posts: 12
Joined: Wed Mar 06, 2024 12:23 pm
Contact:

Re: Changing fixed list of lists to dynamically generated

#3 Post by Lacha »

Hey,

Yes the global declaration has sneaked in by accident. The variable isn't global. I already removed it.

I had two images attached to my first post that help understanding the game. Each car has an arrow on it, showing the direction it will drive when being clicked.
The problem isn't about neighboring cars. It is about blocking each others ways. I attached three pictures of possible cars blocking each others ways.

Meanwhile I have made a new list of dictionaries, which describes the directions a car can go, depending on its coordinates.

Code: Select all

default traffic_car_possibilities = [
    { "coords":[10,11], "up": None, "down": None, "left": ["straight"], "right": ["straight","left","turnright"]},            #4
    { "coords":[11,12], "up": None, "down": None, "left": ["straight","right"], "right": ["straight","left","turnright"]},    #5
    { "coords":[12,13], "up": None, "down": None, "left": ["straight","right"], "right": ["straight","left","turnright"]},    #6
    { "coords":[13,14], "up": None, "down": None, "left": ["straight","right"], "right": ["straight","left"]},                #7
    { "coords":[14,15], "up": None, "down": None, "left": ["straight","right"], "right": ["straight","left"]},                #9
    { "coords":[15,16], "up": None, "down": None, "left": ["straight","right"], "right": ["straight","left"]},                #10
    { "coords":[16,17], "up": None, "down": None, "left": ["straight","right"], "right": ["straight","left"]},                #11
    { "coords":[17,18], "up": None, "down": None, "left": ["straight","right"], "right": ["straight","left"]},                #12
    { "coords":[18,19], "up": None, "down": None, "left": ["straight","right"], "right": ["straight"]},                       #13

    { "coords":[20,21], "up": None, "down": None, "left": ["straight"], "right": ["turnright","turnleft"]},                   #14
    { "coords":[21,22], "up": None, "down": None, "left": ["straight"], "right": ["turnleft"]},                               #15
    { "coords":[22,23], "up": None, "down": None, "left": ["straight"], "right": ["turnleft"]},                               #17
    { "coords":[23,24], "up": None, "down": None, "left": ["straight","turnright"], "right": None},                           #18
    
    { "coords":[30,31], "up": None, "down": None, "left": ["straight"], "right": ["straight","turnleft","turnright"]},        #19
    { "coords":[31,32], "up": None, "down": None, "left": ["straight"], "right": ["straight","turnright"]},                   #20
    { "coords":[32,33], "up": None, "down": None, "left": ["straight"], "right": ["straight","turnright"]},                   #21
    { "coords":[33,34], "up": None, "down": None, "left": ["straight"], "right": ["straight","turnright"]},                   #23
    { "coords":[34,35], "up": None, "down": None, "left": ["straight"], "right": ["straight","turnright"]},                   #24
    { "coords":[35,36], "up": None, "down": None, "left": ["straight"], "right": ["straight","turnright"]},                   #26
    { "coords":[36,37], "up": None, "down": None, "left": ["straight"], "right": ["straight","turnright"]},                   #27
    { "coords":[37,38], "up": None, "down": None, "left": ["straight"], "right": ["straight","turnright"]},                   #28
    { "coords":[38,39], "up": None, "down": None, "left": ["straight","turnleft"], "right": ["straight"]},                       #29

    { "coords":[40,41], "up": None, "down": None, "left": ["straight"], "right": ["turnleft","turnright"]},                       #30
    { "coords":[41,42], "up": None, "down": None, "left": ["straight"], "right": ["turnleft","turnright"]},                       #31
    { "coords":[42,43], "up": None, "down": None, "left": ["straight","turnright"], "right": ["turnleft","turnright"]},                       #32
    { "coords":[43,44], "up": None, "down": None, "left": ["straight","turnleft","turnright"], "right": ["turnleft","turnright"]},                       #33
    { "coords":[44,45], "up": None, "down": None, "left": ["straight","turnleft","turnright"], "right": ["turnright"]},                       #35
    { "coords":[45,46], "up": None, "down": None, "left": ["straight","turnleft","turnright"], "right": ["turnright"]},                       #36

    { "coords":[50,51], "up": None, "down": None, "left": ["straight"], "right": ["straight","turnleft","turnright"]},                       #41
    { "coords":[51,52], "up": None, "down": None, "left": ["straight"], "right": ["straight","turnleft","turnright"]},                       #42
    { "coords":[52,53], "up": None, "down": None, "left": ["straight","turnleft"], "right": ["straight","right","turnleft","turnright"]},                       #43
    { "coords":[53,54], "up": None, "down": None, "left": ["straight","turnleft"], "right": ["straight","right","turnleft","turnright"]},                       #45
    { "coords":[54,55], "up": None, "down": None, "left": ["straight","left","turnleft"], "right": ["straight","turnleft","turnright"]},                       #46
    { "coords":[55,56], "up": None, "down": None, "left": ["straight","left","turnleft"], "right": ["straight","turnleft","turnright"]},                       #47
    { "coords":[56,57], "up": None, "down": None, "left": ["straight","turnleft"], "right": ["straight","turnleft","turnright"]},                       #48
    { "coords":[57,58], "up": None, "down": None, "left": ["straight","turnleft"], "right": ["straight","turnleft","turnright"]},                       #49
    { "coords":[58,59], "up": None, "down": None, "left": ["straight","turnleft","turnright"], "right": ["straight"]},                       #50

    { "coords":[61,62], "up": None, "down": None, "left": ["straight"], "right": ["straight","right","turnleft"]},                       #51
    { "coords":[62,63], "up": None, "down": None, "left": ["straight"], "right": ["straight","right","turnleft"]},                       #52
    { "coords":[63,64], "up": None, "down": None, "left": ["straight","turnright"], "right": ["straight","right","turnleft"]},                       #53
    { "coords":[64,65], "up": None, "down": None, "left": ["straight","turnright"], "right": ["straight","right","turnleft"]},                       #56
    { "coords":[65,66], "up": None, "down": None, "left": ["straight","left","turnright"], "right": ["straight","right"]},                       #57
    { "coords":[66,67], "up": None, "down": None, "left": ["straight","left","turnright"], "right": ["straight","right"]},                       #57
    { "coords":[67,68], "up": None, "down": None, "left": ["straight","left","turnright"], "right": ["straight"]},                       #58
    { "coords":[69,68], "up": None, "down": None, "left": ["straight","left","turnright"], "right": ["straight"]},                       #59


    { "coords":[1,11], "up": ["straight"], "down": ["left", "right"], "left": None, "right" :None},                          #0
    { "coords":[4,14], "up": ["straight"], "down": ["left", "right"], "left": None, "right": None},                          #1
    { "coords":[6,16], "up": ["straight"], "down": ["left", "right"], "left": None, "right": None},                          #2
    { "coords":[8,18], "up": ["straight"], "down": ["left", "right"], "left": None, "right": None},                          #3
    { "coords":[13,23], "up": ["left","right"], "down": ["right"], "left": None, "right":None},                               #8
    { "coords":[21,31], "up": ["left"], "down": ["left","right"], "left": None, "right": None},                               #16#
    { "coords":[32,42], "up": ["left","right"], "down": ["right"], "left": None, "right": None},                   #22#
    { "coords":[34,44], "up": ["left","right"], "down": ["right"], "left": None, "right": None},                              #25#
    { "coords":[38,48], "up": ["left","right"], "down": ["left","right"], "left": None, "right": None},                       #39#
    { "coords":[43,53], "up": ["left"], "down": ["left","right"], "left": None, "right": None},                       #34#
    { "coords":[45,55], "up": ["left"], "down": ["left","right"], "left": None, "right": None},                       #37#
    { "coords":[46,56], "up": ["left"], "down": ["left","right"], "left": None, "right": None},                       #38#
    { "coords":[48,58], "up": ["left","right"], "down": ["left","right"], "left": None, "right": None},                       #40#
    { "coords":[52,62], "up": ["left","right"], "down": ["left","right"], "left": None, "right": None},                       #44#
    { "coords":[54,64], "up": ["left","right"], "down": ["left","right"], "left": None, "right": None},                       #61#
    { "coords":[56,66], "up": ["left","right"], "down": ["left","right"], "left": None, "right": None},                       #60#
    { "coords":[64,74], "up": ["left","right"], "down": ["straight"], "left": None, "right": None},                       #54#
    { "coords":[67,77], "up": ["left","right"], "down": ["straight"], "left": None, "right": None},                       #55#
    
]
Now it is easy to place the cars and pick random directions they can drive to. The difficult part is to check if they oppose another car and block each others ways so both can't drive out.

Best regards

Lacha
Attachments
cars_example3.png
cars_example3.png (12.72 KiB) Viewed 198 times
cars_example2.png
cars_example2.png (19.32 KiB) Viewed 198 times
cars_example1.png
cars_example1.png (11.12 KiB) Viewed 198 times

Lacha
Newbie
Posts: 12
Joined: Wed Mar 06, 2024 12:23 pm
Contact:

Re: Changing fixed list of lists to dynamically generated

#4 Post by Lacha »

Well... I fixed some of my problems. Each time I add a car, I check if the starting coords are in the path of another car and the starting coords of the other car are in the path of the car to be added. If yes I try different paths as long as there are paths left. If none of them works out I remove the car entirely from the game.

Function to check if the cars contain each other:

Code: Select all

    def check_traffic_path(car, path_coords):
        global traffic_cars
        global debugtownmap
        retval = True
        for i in range(1,len(path_coords)):
            u=i-1
            for c in traffic_cars:
                if (path_coords[i] in [c[0],c[1]] and path_coords[u] in [c[0],c[1]]):
                    if car[0] in c[4] or car[1] in c[4]:
                        retval = False
        return retval
Function to setup the cars:

Code: Select all

    def setup_traffic_game():
        global traffic_cars #list of cars to place in the screen
        global traffic_crossings #list of crossings
        global traffic_max_columns
        global traffic_car_possibilities
        traffic_car_possibilities = set_possibilities() #gets the list of possible directions of cars mentioned in my 2nd post
        traffic_cars = [] #list to setup the cars like in my first post
        for p in traffic_car_possibilities:
            usecar = True
            car = [] 
            car.append(p["coords"][0]) #first coord
            car.append(p["coords"][1]) #second coord
            rand_dirs = []
            if p["up"] != None:
                rand_dirs.append("up")
            if p["down"] != None:
                rand_dirs.append("down")
            if p["left"] != None:
                rand_dirs.append("left")
            if p["right"] != None:
                rand_dirs.append("right")
            car.append(renpy.random.choice(rand_dirs)) #direction
            car.append(renpy.random.choice(p[car[2]])) #pathdirection
            path_coords = []
            path_coords = get_traffic_path(car)
            check = check_traffic_path(car, path_coords)
            while not check:
                p[car[2]].remove(car[3])
                if len(p[car[2]]) > 0:
                    car[3] = renpy.random.choice(p[car[2]])
                    path_coords = []
                    path_coords = get_traffic_path(car)
                    check = check_traffic_path(car, path_coords)
                else:
                    usecar = False
                    break
            car.append(path_coords) #pathcoords

            xpos1 = traffic_crossings[car[0]][0]-14
            xpos2 = traffic_crossings[car[1]][0]-14
            ypos1 = traffic_crossings[car[0]][1]-14
            ypos2 = traffic_crossings[car[1]][1]-14
            pos_x = int((xpos1+xpos2)/2)
            pos_y = int((ypos1+ypos2)/2)

            car.append(pos_x) #position x
            car.append(pos_y) #position y
            car.append(True) #show car?
            car.append(False) #is car moving?
            if usecar:
                traffic_cars.append(car)
The only problem I have right now is when multiple cars block each other.
Like in the attached screenshot.

I have a money system in other parts of the game. So I have put a button into the game you can press to remove one car (you can click on it afterwards) from the game. It costs you 1 Credit

It is a workaround that works for me, but I'd love to have a method to check if the game is solvable.

Any ideas anyone?

Best regards and many thanks
Lacha
Attachments
cars_example4.png
cars_example4.png (11.62 KiB) Viewed 110 times

Post Reply

Who is online

Users browsing this forum: Google [Bot]