Alpha - Suggestions, Active bugs, Notes

Hi Team, Contestants,

About this topic
I figured I would add a topic here where I leave some notes, track bugs, and maybe suggest some upgrades with my reasoning, Adding these thoughts early on so that we dont need to have to mess with ideas too late in the challenge.

Possible observed Bugs
Strange Queue Behavior
Some rounds (around three times per match randomly) some matches none at all, the engine skips a turn and queues extend

Possible Cause (Seems random): Tested zookeeper and sometimes he isnt even clsoe to animals
Current fix: Comparing actual move change to posted move, assuming the queue has spiraled, skipping a turn.
**Stabalizes my bot in a turn.

Suggestions (Balance and Features)
A) More Zookeepers (Maybe spawn more every 200 ticks, )
B) Powerup (Blockade) //Turns space you are on into a area that cant be passed (by zookeepers and/or other animals)
C) Trap (Stops a animal for a few 5 turns when passing through a space) (Could be dropped by zookeepers every 20 ticks) (Each Zookeeper would drop 50 traps in a match )

1 Like

Observation Tick Glitch:

I observed:
zooscape-engine | [19:05:24 INF] Game tick 477, Duration = 197 / 150, Duty Cycle = 1.3133333333333332
zooscape-engine | [19:05:24 DBG] Received hub invocation: InvocationMessage { InvocationId: “”, Target: “BotCommand”, Arguments: [ Zooscape.Domain.Models.BotCommand ], StreamIds: [ ] }.
zooscape-engine | [19:05:24 DBG] Received hub invocation: InvocationMessage { InvocationId: “”, Target: “BotCommand”, Arguments: [ Zooscape.Domain.Models.BotCommand ], StreamIds: [ ] }.
zooscape-engine | [19:05:24 INF] Command (Right) enqueued for bot (3b2e3130-1a6d-4902-ad5e-261c855bf8c5). Queue length: 1
zooscape-engine | [19:05:24 DBG] Received hub invocation: InvocationMessage { InvocationId: “476”, Target: “BotCommand”, Arguments: [ Zooscape.Domain.Models.BotCommand ], StreamIds: [ ] }.
zooscape-engine | [19:05:24 INF] Command (Up) enqueued for bot (23016710-31c5-4d97-893c-24750e7ce85c). Queue length: 1
zooscape-engine | [19:05:24 INF] Command (Up) enqueued for bot (6316750f-1633-4f97-856a-a1f9fd5a35de). Queue length: 1
zooscape-engine | [19:05:24 DBG] Received hub invocation: InvocationMessage { InvocationId: “”, Target: “BotCommand”, Arguments: [ Zooscape.Domain.Models.BotCommand ], StreamIds: [ ] }.
zooscape-engine | [19:05:24 INF] Command (Left) enqueued for bot (112a0cbe-03c9-4431-9cef-4cd31bc4e56e). Queue length: 1
zooscape-engine | [19:05:24 INF] Game tick 478, Duration = 8 / 150, Duty Cycle = 0.05333333333333334
zooscape-engine | [19:05:24 DBG] Received hub invocation: InvocationMessage { InvocationId: “”, Target: “BotCommand”, Arguments: [ Zooscape.Domain.Models.BotCommand ], StreamIds: [ ] }.
zooscape-engine | [19:05:24 INF] Command (Down) enqueued for bot (6316750f-1633-4f97-856a-a1f9fd5a35de). Queue length: 2
zooscape-engine | [19:05:24 DBG] Received hub invocation: InvocationMessage { InvocationId: “”, Target: “BotCommand”, Arguments: [ Zooscape.Domain.Models.BotCommand ], StreamIds: [ ] }.
zooscape-engine | [19:05:24 INF] Command (Down) enqueued for bot (112a0cbe-03c9-4431-9cef-4cd31bc4e56e). Queue length: 2
zooscape-engine | [19:05:24 DBG] Received hub invocation: InvocationMessage { InvocationId: “”, Target: “BotCommand”, Arguments: [ Zooscape.Domain.Models.BotCommand ], StreamIds: [ ] }.
zooscape-engine | [19:05:24 INF] Command (Up) enqueued for bot (3b2e3130-1a6d-4902-ad5e-261c855bf8c5). Queue length: 2

So tick 477 seems to skip processing moves for a turn
And suddenly immediately after all bots have a queue of 2,

I do not have more information on this yet, I trimmed my output to only focus on where I have irregularities,

My own output:
Alpha has Awakened 475
Best Move:4
Alpha has Awakened 476
Best Move:4
Alpha has Awakened 477
Best Move:1
Alpha has Awakened 478
CORRECTION SET ON TICK478
PM 1 MX 31 MY 41
TM 4 TX 30 TY 41
Best Move:3
PM ASSUMED UNCHANGED FOR NEXT TURN
Alpha has Awakened 479
Best Move:4
Alpha has Awakened 480
Best Move:4
Alpha has Awakened 481

As mentioned, my temporary solution was to just correct my AI, skip my turn when the engine does.
I see it happening 2 or 3 times per game,

Map behaviour seems normal, My average tickrate on this is 7 ms or so, so nothing that can force a timeout, it also appears to affect all bots on the same tick

Thanks Willie, those are some awesome suggestions for powerups. We have some ideas for powerups in mind already and will certainly add these to our pool. Also, we have specifically designed the game engine in a way that will enable adding more zookeepers so that is also on our radar.

I’ll see if I can make sense of this strange queue behaviour you’re mentioning although nothing pops to mind based on your description here. Do let us know if you are able to narrow it down or find a way to reproduce the problem.

OK, so here we can already see something problematic. The duty cycle is greater than 1 for this game tick, which means it took longer to process than the duration of the clock tick. So yeah, I haven’t investigated why/how exactly that translates to skipped processing of moves but it makes sense that hiccups will be encountered if the duty cycle exceeds 10%.

This is definitely something we should investigate and fix, either by making the processing more efficient or by extending the clock timer. Thanks, for the scrutiny, I think this already points out an improvement we can make.

1 Like

I’ve noticed some weird behavior, cannot confirm yet as I also disabled game engine logs, but if 2 players stand on top of each other and make moves at the same time to the same tile, they both get the pellet score, but plus side it confuses the crap out of the zookeeper… imagine a monkey riding on the zebra playing racing stripes

3 Likes

ezgif-44943561c9d72d
Weird behaviour here as well. Like the zookeeper can eat the player. Seems to only happen when player and zookeeper is at that spot (zookeeper spawn)

Any update on the “engine lagging” issue? Also done a similar approach to Willie to skip the turn to avoid building up a queue. But the Zookeeper still moves which leads to a capture every now & then

This is for running locally (not sure if that might affect anything)

I have the exact same troubles,

Now and then the zookeeper does Capture.

As its an engine issue, We are all in a similar boat,
What I will say however is I track my skips, and get around 3 or 4 per game,

In most games I see myself caught around 4 times for all bots,

Have not played around much, And Im sure that you can code the bot to avoid the keeper enough so that even that isnt an issue,

But I have not given my bot a lot of attention since the post here,
**I failed to improve my bot any time I tried to.

But also lazy,

Hi guys, we have been looking at these occasional lag issues and indeed some game ticks do overrun the time limit. Like @WillieTheron mentions, it’s normally only a handful of ticks from an entire game and we are still trying to establish what is causing it. It might be something like the C# garbage collection kicking in at inopportune moments but we’ll revert when we know.

We are in the process of adding features for phase 2 which will be released after tournament 1 and these have introduced some additional performance hits on the game engine. But the good news is that this forced us to implement some more verbose logging to be able to see which game ticks are overrunning the allowed time, and why. Hopefully that will enable us to have some better visibility on this issue as well.

As soon as that has been incorporated in the public codebase we will let you all know.

1 Like

@deefstes, There are times the new game engine (2025.2.0) gets stuck. Upon a bit of digging from my side, it seems to be getting stuck in Domain/Utilities/GlobalSeededRandomizer.cs in the GetRandomElement function.

public T? GetRandomElement<T>(IEnumerable<T> source, Func<T, bool> predicate, int timeout)
    {
        var stopwatch = new Stopwatch();

        do
        {
            var retval = GetRandomElement(source);
            if (predicate(retval))
                return retval;
        } while (stopwatch.ElapsedMilliseconds < timeout);

        return default;
    }

There is no stopwatch.Start() after stopwatch is initialised so the while loop there gets stuck in an infinite loop or much longer than the intended timeout as stopwatch.ElapsedMilliseconds is always 0.

2 Likes

That is very astute, @jiro90 . Thanks for pointing it out. We did actually pick this up with last weekend’s friendly tournament and have fixed the bug. You can expect a release with that any day now.

1 Like

I have a random question since im too lazy to go look at the game engine, does the tick time include processing the game round and sending the game state to the players, or does it wait tick ms after game state is sent before processing next tick.

So in short if game tick is ex 150ms we actually have 10ms in theory after receiving the game state to post next action?

If thats is the case, it would be nice to have a queue count on your animal, and a way to override it so you can pre queue steps but also have the ability to change it incase a zookeeper happens to spot you

Hi @Kortgat , that is a good question that is worth explaining a bit.

So first of all, each bot does have a command queue which is normally 10 command long but can be configured. However, through our gameplay testing we’ve learned that there really is very little value in the command queue. But if you’re moving up for instance and you’ve already calculated that you want to take the right turn that is 4 cells above you, you could immediately queue 4xUP and 1xRIGHT. But that is about it. I’m not sure how you would change your mind based on whether the zookeeper spotted you. How would you know that the zookeeper spotted you?

As for the timing, yes, the game loop’s processing and everything has to happen within the allocated 200ms. One of the first things the game loop does is to read the commands from the bots, and one of the last things the game loop does is to provide feedback to the bots. The percentage of the tick time that is taken up by the game engine to perform its calculations and processing is called the duty cycle and you can see the duty cycle for each tick and the aggregated stats for the whole game in the game engine logs.

We’ve put in a lot of work to optimise the performance of the game engine for this very reason. For the first tournament the 99th percentile value for the duty cycle was 5%. That means that 99% of all the game ticks completed all their processing in 10ms or less, leaving the bots with 190ms to calculate their next move and get the command through to the game engine.

For phase 2 the game engine has some more intense calculations to perform but, even so, we’re rarely seeing duty cycles exceeding 20%.