Callback Chaining

Passing the baton in a relay race against the zombies!

Originally, I programmed the entire zombie phase as a for_next looping jumping through functions to control each part. Let’s breakdown the zombie phase.

Zombie Phase:

1.Night activation – if its night and a torch is on, activate any zombies that can see the beam

2. Activate all the zombies on in game (basically on the board) – I an activate each tile in sequence, with a short pause of 1 second.

3. Spawn Phase. For each spawn tile – draw a spawn card.
Are the zombies in reserve to spawn?
If no- extra activation for all zombies of that type.
If yes- spawn zombies at spawn point. (if include activation – then activate as well)

Is the spawn card an “extra activation” for zombie type in game? – then do activation.

Is the spawn an Abomination and is already on in game?
If yes – then activate.
If no – draw random Abomination card and spawn

The for loop works, but when I want to animate the zombie graphic on a tk.inter canvas, the loops execute before the tk.after has a chance to stack them in its event loop. To get around this, I have had to reprogram it using callback event chains. This go through each part in seqence and the callback places the delay to tk.after() function.

Here is an example of a chained callback:

items = ['a', 'b', 'c', 'd']

def do_items(i, max_times, items, on_complete=None):
    if i >= len(items):
        if on_complete:
            on_complete()
        return
    
    print("\n\ndo_items", i, items[i], " max ", max_times)

    # Chain into do_it
    do_it(0, max_times, items, lambda: do_items(i + 1, max_times, items, on_complete))


def do_it(i, max_times, items, on_complete=None):
    if i >= len(items):
        if on_complete:
            on_complete()
        return
    
    print("do_it", i, items[i], " max ", max_times)
    
    # Chain into do_it_again
    do_it_again(0, max_times, items, lambda: do_it(i + 1, max_times, items, on_complete))


def do_it_again(pos, max_times, items, on_complete=None):
    if pos >= max_times:
        if on_complete:
            on_complete()
        return
    
    print("do_it_again", pos, items[pos % len(items)], " max ", max_times)
    
    # Chain into do_whatever, then continue recursion
    do_whatever(pos, items)
    do_it_again(pos + 1, max_times, items, on_complete)


def do_whatever(pos, items):
    print("do_whatever", pos, items)


do_items(0, 3, items)

Similar Posts