AI League - King's Gambit Cup

I don’t know how he won. I had more spent. Neither of us scored on each other either.

From what I heard, he gets more DP as he attacks more units , I have been trying to figure out how to win against him.

This has been happening for a couple of days now I think others are having similar issues.

No it’s not a glitch, when the someone submits their code twice, one that beats you and one that loses to you, you will see one loss and one win in your simulations, but when you spectate and battle someone, the simulation you see is their most recent code. If someone submited their code that loses to you last, then you will see you beating them even if your simulations said you lost to them.

1 Like

So, in the final round of simulations do both codes count or only one of them?

The last submited is the one they will run final sims with.

1 Like

I see that I win against them now.

1 Like

Hey @Bryukh were you intending for the tournament to finish at Midnight Pacific Time? Because it seems to be scheduled for 1 AM PT, possibly due to a mix up with daylight savings.

Right now it seems to be scheduled to end at midnight PST.

But we’re on PDT, which is an hour ahead of PDT

???
(20charssssssssssssssssss)

fairly strong unsubmitted code (performs decent against top 10 but never ranked so might have some edge cases)

doStuff = False
boardLength = 8
goldCutoff = 147

lastFling = -100

units = {
    "pawn":     [0, 0, 2, 0, 2, 0, 0],
    "bishop":   [1, 1, 1, 0, 1, 1, 1],
    "knight":   [0, 2, 2, 0, 2, 2, 0],
    "rook":     [1, 1, 1, 4, 1, 1, 1],
    "queen":    [3, 3, 3, 5, 3, 3, 3]
}

unitCost = {
    "pawn": 15,
    "bishop": 40,
    "knight": 35,
    "rook": 50,
    "queen": 75
}

unitPoints = {
    "pawn": 1,
    "bishop": 3,
    "knight": 3,
    "rook": 5,
    "queen": 9
}

allUnits = ["pawn", "bishop", "knight", "rook", "queen"]

pawnSwap = 1

lookup = {}

for unitName, attackPattern in units.items():
    lookup[unitName] = []
    for row in range(boardLength):
        boardPattern = [0] * boardLength
        for i, dmg in enumerate(attackPattern):
            boardIndex = row + (i - 3)
            if 0 <= boardIndex < boardLength:
                boardPattern[boardIndex] = dmg
        lookup[unitName].append(boardPattern)

moveCooldowns = {}

while True:
    numAllies = [0] * boardLength
    numEnemies = [0] * boardLength
    enemyPattern = [0] * boardLength
    rowDiffs = [0] * boardLength
    minDists = [1000] * boardLength
    typesNeeded = {
        "pawn": False,
        "bishop": False,
        "knight": False,
        "rook": False,
        "queen": False
    }
    
    maxDiff = 0
    maxRow = 0
    minUnitx = 1000
    minUnit = None
    
    myUnits = hero.findMyUnits()
    enemyUnits = hero.findEnemyUnits()
    
    goodUnits = ["bishop"] if len(enemyUnits) == 0 or hero.time < 7.2 else ["queen"]
    for unitName in goodUnits:
        typesNeeded[unitName] = True
    
    for unit in myUnits:
        typesNeeded[unit.type] = True
        unitrow = unit.row - 1
        numAllies[unitrow] += 1
        if hero.isReady("fling"):
            rowDiffs[unitrow] -= unitPoints[unit.type] * (1 + unit.health/unit.maxHealth)
    for unit in enemyUnits:
        unitrow = unit.row - 1
        distFactor =  1 + (50-unit.x)/160
        rowDiffs[unitrow] += unitPoints[unit.type] * (1 + unit.health/unit.maxHealth) * distFactor
        numEnemies[unitrow] += distFactor
        atkFactor = (1 + (unit.speed > 7.5)) * distFactor
        enemyPattern = [enemyPattern[0] + atkFactor * lookup[unit.type][unitrow][0],enemyPattern[1] + atkFactor * lookup[unit.type][unitrow][1],enemyPattern[2] + atkFactor * lookup[unit.type][unitrow][2],enemyPattern[3] + atkFactor * lookup[unit.type][unitrow][3],enemyPattern[4] + atkFactor * lookup[unit.type][unitrow][4],enemyPattern[5] + atkFactor * lookup[unit.type][unitrow][5],enemyPattern[6] + atkFactor * lookup[unit.type][unitrow][6],enemyPattern[7] + atkFactor * lookup[unit.type][unitrow][7]]
        if unit.x < minDists[unitrow]:
            minDists[unitrow] = unit.x
            if unit.x < minUnitx:
                minUnitx = unit.x
                minUnit = unit
    
    for row in range(boardLength):
        if rowDiffs[row] > maxDiff:
            maxDiff = rowDiffs[row]
            maxRow = row
    
    limit = hero.gold >= goldCutoff
    if limit:
        doStuff = True
    
    imminent = -1
    if maxDiff >= 2.5 and lastFling + 10 - hero.time < (minDists[maxRow] - 12)/7:
        imminent = maxRow
    
    advantages = {}
    for unitName in allUnits:
        if not typesNeeded[unitName]:
            continue
        advantages[unitName] = [0, 0, 0.001, 0, 0, 0.001, 0, 0]
        for row in range(boardLength):
            myPattern = lookup[unitName][row]
            myDamage = [myPattern[0]*numEnemies[0],myPattern[1]*numEnemies[1],myPattern[2]*numEnemies[2],myPattern[3]*numEnemies[3],myPattern[4]*numEnemies[4],myPattern[5]*numEnemies[5],myPattern[6]*numEnemies[6],myPattern[7]*numEnemies[7]]
            myDamage[imminent] = 0
            risk = 0 if unitName == "pawn" else 2 * enemyPattern[row] - rowDiffs[row]/100
            myAdv = max(myPattern) + max(myDamage) - risk - unitCost[unitName]/20 + Math.random()/1000
            if numEnemies[row] == 0:
                myAdv -= unitCost[unitName]/10
            if row == imminent:
                myAdv -= unitCost[unitName]/10
            advantages[unitName][row] += myAdv
    
    if hero.time > 178.5:
        lmao = hero.gold + 20 * (180 - hero.time)
        if lmao % 15 >= 10 and lmao >= 40:
            hero.summon("bishop", 3)
        elif lmao % 15 >= 5 and lmao >= 30:
            hero.summon("knight", 3)
        sumAt = 3
        if minUnit:
            sumAt = minUnit.row + pawnSwap
            if minUnit.row == 1:
                sumAt = 2
            elif minUnit.row == boardLength:
                sumAt = boardLength - 1
            else:
                pawnSwap *= -1
        hero.summon("pawn", sumAt)
    elif minUnitx <= 15 and minUnit.health <= 10 and hero.gold >= 70:
        hero.summon("queen", minUnit.row)
    elif minUnitx <= 23 and minUnitx >= 15 and hero.gold >= 15:
        sumAt = minUnit.row + pawnSwap
        if minUnit.row == 1:
            sumAt = 2
        elif minUnit.row == boardLength:
            sumAt = boardLength - 1
        else:
            pawnSwap *= -1
        hero.summon("pawn", sumAt)
    elif hero.isReady("fling") and maxDiff >= 2.5 and not limit:
        lastFling = hero.time
        hero.ability("fling", maxRow + 1)
    elif hero.isReady("placeCrate") and minUnit and minUnitx < 1000 and not limit:
        hero.ability("placeCrate", minUnit.row, minUnitx - 1)
    else:
        for unit in myUnits:
            if not (unit in moveCooldowns):
                moveCooldowns[unit] = hero.time
            if hero.time < moveCooldowns[unit] or hero.gold > goldCutoff - 5:
                continue
            
            curRow0 = unit.row - 1
            bestRow0  = curRow0
            bestScore = advantages[unit.type][curRow0]
            for d in (-2, -1, 1, 2):
                tr = curRow0 + d
                if 0 <= tr < boardLength and numAllies[tr] == 0:
                    if advantages[unit.type][tr] > bestScore + 0.001:
                        bestScore = advantages[unit.type][tr]
                        bestRow0  = tr
            
            if bestRow0 != curRow0:
                direction = "down" if bestRow0 < curRow0 else "up"
                moveCooldowns[unit] = hero.time + 2
                numAllies[curRow0] -= 1
                numAllies[bestRow0] += 1
                hero.moveUnit(unit, direction, abs(bestRow0 - curRow0))
        if hero.gold >= goldCutoff:
            doStuff = True
        if doStuff:
            bestAdvantage = float("-inf")
            bestUnit = None
            bestRow = None
            for unitName in goodUnits:
                for row in range(boardLength):
                    myAdv = advantages[unitName][row]
                    if myAdv > bestAdvantage and numAllies[row] == 0 and row != imminent:
                        bestAdvantage = myAdv
                        bestUnit = unitName
                        bestRow = row
            
            if bestUnit and hero.gold >= unitCost[bestUnit]:
                hero.summon(bestUnit, bestRow + 1)
                if hero.gold < 5:
                    doStuff = False
            if bestUnit == None:
                if hero.gold >= goldCutoff:
                    hero.summon("pawn", 3)
                doStuff = False
2 Likes

main features are:

  • an advantage function that says how good a piece is on a row, so summon/swap logic is easier
  • pawn defense (idea from skye)
  • in the last few seconds chooses pieces to end up with 0 gold to spare instead of spamming pawns
  • uses bishops if winning, they give the opponent less DP per gold spent

did not add sacrifice logic, but did code in that sacrifice buffed pieces are more of a threat

2 Likes

Hi everybody! My name is HarryCHLao in the tournament. I just found this forum.
@Bryukh This is unfair to prolong the tournament as it ended.

  1. Before it ended, there was a timer to indicate the deadline.
  2. As the tournament ended on 31 May, I thought that it ended and have never visited it anymore, as I have been busying on my study (exam days).
  3. You have not notified me for the deadline extension. I didn’t know this forum. I have not received any notification from CodeCombat by e-mail.
  4. It is unfair to be challenged by others without knowing.

CodeCombat posted the deadline. Why doesn’t CodeCombat keep the promise? I am really disappointed. Is it true that when someone says he/she has not posted the best code, and then you can reopen it easily? What does the timer for?

1 Like

Hi @HarryCHLao! Welcome to the CodeCombat Discourse! Its always cool to see a fellow AI league competitor join. This is a safe place to chat and ask for level help. Before you begin your journey, could you please go through our rules that make this discourse an awesome place? It helps us all :grin: We hope you enjoy your stay!!

The reason the tournament was postponed was that originally the past 12 arenas had all ended at 12 P.M. PST and most of the people who had participated in past areans including me though that it would end then, and didn’t bother checking the arean with the countdown on it. I do understand your frustration though, and I do agree that the admins should have done a better job with making sure everyone knew about the changed end date.

I’m sure this has been mentioned before, but it seems that the dominant strategy is to not submit until the very last moment. The example code posted above had been worked on throughout the duration of the tournament and beats each of the top 25, which I don’t think would have been possible if it had been submitted publicly.

If it’s too much of a problem, perhaps a solution for future tournaments would be to advance the top 8 scorers into a single/double elimination tournament with seeding based on score and give them 2-3 more days to privately submit their final code, so last-minute snipers would at least need to put out something decent even if it isn’t full-strength.

1 Like

Sounds a bit complicated…

A previously proposed system is a 24 hour blind submission window where you can submit your code but other people can’t see it or test against it. @HarryCHLao My submitted code at 8AM PT 5/31 wasn’t even in the top 50, because I had disabled a few systems so nobody could see figure out my strategies, and my unsubmitted code was really good. I understand your frustration, but because it has always been midnight Pacific time, I was still tweaking it a little and had planned to build a few more systems. And I’m being completely honest here, my unsubmitted code at the original end time did beat yours when I first tested it. However, I do believe they should have sent out an email announcement about the extension as the original end time was a mistake that was not fixed until many hours after that end time.

2 Likes

oops i forgot this tournament existed
my code is very outdated
eh too late ig

3 Likes

@Bryukh I was just checking the simulations and I am having the same issue as before where I it shows that I am losing, but when I actually spectate, it says I win.