Пример #1
0
        private void PrepareTimeLimit(State state, int player, DistanceMap distanceMap)
        {
            gen++;
            timeLimit = Env.MAX_TICK_COUNT - state.time;
            for (var i = 0; i < state.players[player].lineCount; i++)
            {
                var line = state.players[player].line[i];
                used[line] = gen;
                for (var other = 0; other < state.players.Length; other++)
                {
                    if (other == player || state.players[other].status == PlayerStatus.Eliminated)
                    {
                        continue;
                    }

                    if (distanceMap.times1[other, line] != -1 && distanceMap.times1[other, line] < timeLimit)
                    {
                        timeLimit = distanceMap.times1[other, line];
                    }

                    if (distanceMap.times2[other, line] != -1 && distanceMap.times2[other, line] < timeLimit)
                    {
                        timeLimit = distanceMap.times2[other, line];
                    }
                }
            }
        }
Пример #2
0
 public void Start(State state, int player, DistanceMap distanceMap)
 {
     PrepareTimeLimit(state, player, distanceMap);
     len          = 0;
     startLen     = 0;
     pos          = state.players[player].arrivePos;
     started      = state.players[player].lineCount > 0;
     dir          = state.players[player].dir;
     fixedNextDir = null;
     time         = 0;
     shiftTime    = state.players[player].shiftTime;
     nitroLeft    = state.players[player].nitroLeft;
     slowLeft     = state.players[player].slowLeft;
 }
Пример #3
0
        public void BuildPath(State state, DistanceMap distanceMap, int player, ushort target)
        {
            len         = 0;
            originalLen = 0;
            if (target == ushort.MaxValue)
            {
                return;
            }

            if (distanceMap.times2[player, target] < distanceMap.times1[player, target])
            {
                var start = state.players[player].arrivePos;
                int cur   = target;
                while (true)
                {
                    var next = distanceMap.paths2[player, cur];
                    if (next == -1)
                    {
                        break;
                    }
                    dirs[len++] = ((ushort)next).DirTo((ushort)cur);
                    originalLen++;
                    cur = next;
                }

                while (cur != start)
                {
                    var next = distanceMap.paths1[player, cur];
                    dirs[len++] = ((ushort)next).DirTo((ushort)cur);
                    originalLen++;
                    cur = next;
                }
            }
            else
            {
                var start = state.players[player].arrivePos;
                for (int cur = target; cur != start;)
                {
                    var next = distanceMap.paths1[player, cur];
                    dirs[len++] = ((ushort)next).DirTo((ushort)cur);
                    originalLen++;
                    cur = next;
                }
            }
        }
Пример #4
0
        public bool Generate(State state, int player, DistanceMap distanceMap, InterestingFacts facts, ReliablePathBuilder pathBuilder, byte allowedDirectionsMask = 0xFF)
        {
            pathBuilder.Start(state, player, distanceMap);
            while (true)
            {
                if (pathBuilder.dir == null)
                {
                    dirs[0]       = Direction.Up;
                    dirs[1]       = Direction.Left;
                    dirs[2]       = Direction.Right;
                    dirs[3]       = Direction.Down;
                    dirChances[0] = 1;
                    dirChances[1] = 1;
                    dirChances[2] = 1;
                    dirChances[3] = 1;
                    dirsCount     = 4;
                    random.Shuffle(dirs);
                }
                else
                {
                    dirs[0]   = pathBuilder.dir.Value;
                    dirs[1]   = (Direction)(((int)dirs[0] + 1) % 4);
                    dirs[2]   = (Direction)(((int)dirs[0] + 3) % 4);
                    dirsCount = 3;

                    if (random.Next(2) == 0)
                    {
                        var tmp = dirs[1];
                        dirs[1] = dirs[2];
                        dirs[2] = tmp;
                    }

                    if (random.Next(sameDirChance) == 0)
                    {
                        var other = random.Next(1, 3);
                        var tmp   = dirs[0];
                        dirs[0]     = dirs[other];
                        dirs[other] = tmp;
                    }
                }

                var found = false;
                for (var i = 0; i < dirsCount; i++)
                {
                    var nextDir = dirs[i];
                    if (pathBuilder.len == 0 && (allowedDirectionsMask & (1 << (int)nextDir)) == 0)
                    {
                        continue;
                    }

                    var nextPos = pathBuilder.pos.NextCoord(nextDir);
                    if (nextPos == ushort.MaxValue)
                    {
                        continue;
                    }

                    if (!pathBuilder.TryAdd(state, player, distanceMap, facts, nextPos))
                    {
                        continue;
                    }

                    found = true;
                    break;
                }

                if (!found)
                {
                    return(false);
                }

                if (pathBuilder.started &&
                    state.territory[pathBuilder.pos] == player &&
                    (!pathBuilder.useTerritoryTtl || facts.territoryTtl[pathBuilder.pos] > pathBuilder.time))
                {
                    return(true);
                }
            }
        }
        public void Build(State state, DistanceMap distanceMap)
        {
            for (int i = 0; i < state.players.Length; i++)
            {
                places[i]          = i;
                potentialScores[i] = 0;
            }

            for (int i = 0; i < state.players.Length - 1; i++)
            {
                for (int k = i + 1; k < state.players.Length; k++)
                {
                    if (state.players[places[i]].score < state.players[places[k]].score)
                    {
                        var tmp = places[i];
                        places[i] = places[k];
                        places[k] = tmp;
                    }
                }
            }

            for (int i = 0; i < state.players.Length; i++)
            {
                if (state.players[i].status == PlayerStatus.Eliminated || state.players[i].status == PlayerStatus.Broken)
                {
                    continue;
                }
                sawCollectTime[i]     = int.MaxValue;
                sawCollectDistance[i] = int.MaxValue;
                distCount[i]          = 0;
                pathsToOwned[i].BuildPath(state, distanceMap, i, distanceMap.nearestOwned[i]);
            }

            for (ushort c = 0; c < Env.CELLS_COUNT; ++c)
            {
                territoryTtl[c] = int.MaxValue;
            }

            for (int b = 0; b < state.bonusCount; b++)
            {
                if (state.bonuses[b].type == BonusType.Saw)
                {
                    for (var i = 0; i < state.players.Length; i++)
                    {
                        if (state.players[i].status == PlayerStatus.Eliminated || state.players[i].status == PlayerStatus.Broken)
                        {
                            continue;
                        }

                        var st = distanceMap.times1[i, state.bonuses[b].pos];
                        if (st != -1 && st != int.MaxValue && st < sawCollectTime[i])
                        {
                            sawCollectTime[i] = st;
                        }

                        var sd = distanceMap.distances1[i, state.bonuses[b].pos];
                        if (sd != -1 && sd != int.MaxValue && sd < sawCollectDistance[i])
                        {
                            sawCollectDistance[i] = sd;
                        }

                        st = distanceMap.times2[i, state.bonuses[b].pos];
                        if (st != -1 && st != int.MaxValue && st < sawCollectTime[i])
                        {
                            sawCollectTime[i] = st;
                        }

                        sd = distanceMap.distances2[i, state.bonuses[b].pos];
                        if (sd != -1 && sd != int.MaxValue && sd < sawCollectDistance[i])
                        {
                            sawCollectDistance[i] = sd;
                        }
                    }
                }
            }

            var territoryVersion = state.territoryVersion;

            backup.Backup(state);
            while (!state.isGameOver)
            {
                var ended = 0;
                for (var i = 0; i < state.players.Length; i++)
                {
                    if (state.players[i].status == PlayerStatus.Eliminated || state.players[i].status == PlayerStatus.Broken)
                    {
                        ended++;
                        continue;
                    }

                    if (state.players[i].arriveTime != 0)
                    {
                        if (pathsToOwned[i].len < 0)
                        {
                            ended++;
                        }
                        continue;
                    }

                    if (pathsToOwned[i].len <= 0)
                    {
                        ended++;
                    }

                    commands[i] = pathsToOwned[i].ApplyNext(state, i);
                    distCount[i]++;
                }

                if (ended == state.players.Length)
                {
                    for (int i = 0; i < state.players.Length; i++)
                    {
                        potentialScores[i] = state.players[i].score - backup.players[i].score;
                    }
                    break;
                }

                state.NextTurn(commands, false);
                if (state.territoryVersion != territoryVersion)
                {
                    territoryVersion = state.territoryVersion;
                    for (ushort c = 0; c < Env.CELLS_COUNT; ++c)
                    {
                        if (territoryTtl[c] == int.MaxValue && state.territory[c] != backup.territory[c])
                        {
                            territoryTtl[c] = state.time - backup.time;
                        }
                    }
                }

                for (var i = 0; i < state.players.Length; i++)
                {
                    if (state.players[i].status == PlayerStatus.Eliminated || state.players[i].status == PlayerStatus.Broken)
                    {
                        continue;
                    }
                    if (state.players[i].sawsCollected > 0)
                    {
                        if (state.time - backup.time < sawCollectTime[i])
                        {
                            sawCollectTime[i] = state.time - backup.time;
                        }
                        if (distCount[i] < sawCollectDistance[i])
                        {
                            sawCollectDistance[i] = distCount[i];
                        }
                    }
                }
            }


            backup.Restore(state);

            for (var i = 0; i < state.players.Length; i++)
            {
                pathsToOwned[i].Reset();
            }
        }
Пример #6
0
        public bool TryAdd(State state, int player, DistanceMap distanceMap, InterestingFacts facts, ushort nextPos)
        {
            if (used[nextPos] == gen)
            {
                return(false);
            }

            var nextDir = pos.DirTo(nextPos);

            if (fixedNextDir != null && fixedNextDir.Value != nextDir)
            {
                return(false);
            }

            var nextTime = time + shiftTime;

            if (nextTime > timeLimit || nextTime == timeLimit && (!started || state.territory[nextPos] != player || useTerritoryTtl && facts.territoryTtl[nextPos] <= nextTime))
            {
                return(false);
            }

            var nextNitroLeft = nitroLeft;
            var nextSlowLeft  = slowLeft;

            if (nextNitroLeft > 0)
            {
                nextNitroLeft--;
            }
            if (nextSlowLeft > 0)
            {
                nextSlowLeft--;
            }
            for (var b = 0; b < state.bonusCount; b++)
            {
                if (state.bonuses[b].pos == nextPos)
                {
                    if (state.bonuses[b].type == BonusType.S)
                    {
                        nextSlowLeft += state.bonuses[b].ActiveTicks(player);
                    }
                    else if (state.bonuses[b].type == BonusType.N)
                    {
                        nextNitroLeft += state.bonuses[b].ActiveTicks(player);
                    }
                }
            }

            var nextShiftTime = Player.GetShiftTime(nextNitroLeft, nextSlowLeft);
            var escapeTime    = nextTime + nextShiftTime;

            var nextTimeLimit = timeLimit;
            var nextStarted   = started || state.territory[nextPos] != player ||
                                useTerritoryTtl && facts.territoryTtl[nextPos] <= nextTime;
            Direction?nextFixedNextDir = null;

            if (nextStarted)
            {
                for (var other = 0; other < state.players.Length; other++)
                {
                    if (other == player || state.players[other].status == PlayerStatus.Eliminated)
                    {
                        continue;
                    }

                    var otherTimeToPos = distanceMap.times1[other, nextPos];
                    if (otherTimeToPos != -1 && otherTimeToPos != int.MaxValue)
                    {
                        if (otherTimeToPos < nextTimeLimit)
                        {
                            nextTimeLimit = otherTimeToPos;
                        }

                        if (state.players[other].arrivePos == nextPos)
                        {
                            nextTimeLimit = -1;
                            break;
                        }

                        var finished        = state.territory[nextPos] == player && (!useTerritoryTtl || facts.territoryTtl[nextPos] > nextTime);
                        var enterLineLen    = len - startLen + state.players[player].lineCount;
                        var lineLen         = finished ? 0 : enterLineLen + 1;
                        var canKillOnEnter  = distanceMap.enterLineLens1[other, nextPos] <= enterLineLen;
                        var canKillOnEscape = distanceMap.lineLens1[other, nextPos] <= lineLen;
                        var canKillInside   = distanceMap.enterLineLens1[other, nextPos] <= lineLen;

                        if (otherTimeToPos < escapeTime && canKillOnEscape)
                        {
                            nextTimeLimit = -1;
                            break;
                        }

                        var otherEnterTime = distanceMap.enterTimes1[other, nextPos];
                        if (otherEnterTime != -1 && otherEnterTime != int.MaxValue)
                        {
                            if (otherEnterTime < nextTime && canKillOnEnter)
                            {
                                nextTimeLimit = -1;
                                break;
                            }

                            if (otherEnterTime == nextTime && canKillInside)
                            {
                                nextTimeLimit = -1;
                                break;
                            }

                            if (otherEnterTime < escapeTime && canKillInside)
                            {
                                var enterCommands = distanceMap.enterCommands1[other, nextPos];
                                if ((enterCommands & (enterCommands - 1)) != 0)
                                {
                                    nextTimeLimit = -1;
                                    break;
                                }

                                for (int d = 0; d < 4; d++)
                                {
                                    if (1 << d == enterCommands)
                                    {
                                        nextFixedNextDir = (Direction)d;
                                        break;
                                    }
                                }
                            }
                        }
                    }

                    otherTimeToPos = distanceMap.times2[other, nextPos];
                    if (otherTimeToPos != -1 && otherTimeToPos != int.MaxValue)
                    {
                        if (otherTimeToPos < nextTimeLimit)
                        {
                            nextTimeLimit = otherTimeToPos;
                        }

                        if (state.players[other].arrivePos == nextPos)
                        {
                            nextTimeLimit = -1;
                            break;
                        }

                        var finished        = state.territory[nextPos] == player && (!useTerritoryTtl || facts.territoryTtl[nextPos] > nextTime);
                        var enterLineLen    = len - startLen + state.players[player].lineCount;
                        var lineLen         = finished ? 0 : enterLineLen + 1;
                        var canKillOnEnter  = distanceMap.enterLineLens2[other, nextPos] <= enterLineLen;
                        var canKillOnEscape = distanceMap.lineLens2[other, nextPos] <= lineLen;
                        var canKillInside   = distanceMap.enterLineLens2[other, nextPos] <= lineLen;

                        if (otherTimeToPos < escapeTime && canKillOnEscape)
                        {
                            nextTimeLimit = -1;
                            break;
                        }

                        var otherEnterTime = distanceMap.enterTimes2[other, nextPos];
                        if (otherEnterTime != -1 && otherEnterTime != int.MaxValue)
                        {
                            if (otherEnterTime < nextTime && canKillOnEnter)
                            {
                                nextTimeLimit = -1;
                                break;
                            }

                            if (otherEnterTime == nextTime && canKillInside)
                            {
                                nextTimeLimit = -1;
                                break;
                            }

                            if (otherEnterTime < escapeTime && canKillInside)
                            {
                                var enterCommands = distanceMap.enterCommands2[other, nextPos];
                                if ((enterCommands & (enterCommands - 1)) != 0)
                                {
                                    nextTimeLimit = -1;
                                    break;
                                }

                                for (int d = 0; d < 4; d++)
                                {
                                    if (1 << d == enterCommands)
                                    {
                                        nextFixedNextDir = (Direction)d;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if (nextTime > nextTimeLimit ||
                nextTime == nextTimeLimit && (!started || state.territory[nextPos] != player || useTerritoryTtl && facts.territoryTtl[nextPos] <= nextTime))
            {
                return(false);
            }

            coords[len]   = nextPos;
            times[len]    = nextTime;
            used[nextPos] = gen;
            if (!started && nextStarted)
            {
                startLen = len;
            }

            len++;
            fixedNextDir = nextFixedNextDir;
            dir          = nextDir;
            pos          = nextPos;
            time         = nextTime;
            timeLimit    = nextTimeLimit;
            nitroLeft    = nextNitroLeft;
            slowLeft     = nextSlowLeft;
            shiftTime    = nextShiftTime;
            started      = nextStarted;
            return(true);
        }