Example #1
0
 def testBasic(self):
     sp1 = scene.Sphere((123456, 123456, 123456), 90000)
     sp2 = scene.Sphere((234567, 234567, 234567), 90000)
     self.tree.insert(sp1, 0)
     self.tree.insert(sp2, 1)
     sp3 = scene.Sphere((179011, 179011, 179011), 10000)
     self.assertEqual(self.tree.intersect(sp3, True), [])
     tmpResult = self.tree.intersect(sp3, False)
     tmpResult.sort()
     self.assertEqual(tmpResult, [0, 1])
     self.tree.delete(0)
     self.assertEqual(self.tree.intersect(sp3, False), [1])
Example #2
0
 def testAgainstNaiveImpl(self):
     number = 100
     sqr = lambda x: x * x
     rand = myrand.MyRand()
     sp = []
     for i in range(number):
         sp.append(scene.Sphere(
             (rand.rand() % 800000 + 100000, rand.rand() % 800000 + 100000, rand.rand() % 800000 + 100000),
             rand.rand() % 100000))
         self.tree.insert(sp[i], i)
     for i in range(number):
         temp = []
         for j in range(number):
             if sqr(sp[i].center[0] - sp[j].center[0]) + sqr(sp[i].center[1] - sp[j].center[1]) + sqr(
                             sp[i].center[2] - sp[j].center[2]) < sqr(sp[i].radius):
                 temp.append(j)
         treeResult = self.tree.intersect(sp[i], True)
         treeResult.sort()
         self.assertEqual(treeResult, temp)
         temp = []
         for j in range(number):
             if sqr(sp[i].center[0] - sp[j].center[0]) + sqr(sp[i].center[1] - sp[j].center[1]) + sqr(
                             sp[i].center[2] - sp[j].center[2]) < sqr(sp[i].radius + sp[j].radius):
                 temp.append(j)
         treeResult = self.tree.intersect(sp[i], False)
         treeResult.sort()
         self.assertEqual(treeResult, temp)
Example #3
0
 def addNewPlayer(self, playerId: int, aiId: int, pos: tuple, radius: int):
     sphere = scene.Sphere(pos, radius)
     self._scene.insert(sphere, playerId)
     newStatus = PlayerStatus()
     newStatus.health = int((radius / 100)**3)
     newStatus.maxHealth = newStatus.health
     newStatus.aiId = aiId
     self._players[playerId] = newStatus
Example #4
0
 def playerMove(self, playerId: int):
     oldPos = self._scene.getObject(playerId).center
     r = self._scene.getObject(playerId).radius
     speed = self._players[playerId].speed
     newPos = tuple(oldPos[i] + speed[i] for i in range(3))
     if self.outsideMap(newPos, r):
         newPos2 = list(newPos)
         for i in range(3):
             if newPos2[i] + r > self._mapSize:
                 newPos2[i] = self._mapSize - r
             elif newPos[i] - r < 0:
                 newPos2[i] = r
         newPos = tuple(newPos2)
     newSphere = scene.Sphere(newPos, r)
     self._scene.modify(newSphere, playerId)
     self._changeList.append(
         self.makeChangeJson(playerId, self._players[playerId].aiId,
                             newSphere.center, newSphere.radius))
Example #5
0
 def healthChange(self, playerId: int, delta: int):
     player = self._players.get(playerId)
     if player is None:
         return
     if player.death:
         return
     player.healthChange(delta)
     if delta < 0:
         self._damage -= delta
     newHealth = player.health
     if newHealth < player.maxHealth // 4:
         self.playerDie(playerId)
     else:
         newRadius = (newHealth**(1 / 3)) * 100
         newSphere = scene.Sphere(
             self._scene.getObject(playerId).center, newRadius)
         self._scene.modify(newSphere, playerId)
         self._changedPlayer.add(playerId)
Example #6
0
 def nutrientMove(self, playerId: int):
     if playerId == 0:
         return
     sphere = self._scene.getObject(playerId)
     if self._players[0].death == False:
         bosssphere = self._scene.getObject(0)
     pos = tuple(
         self._rand.randIn(self._mapSize - 2 * sphere.radius) +
         sphere.radius for _ in range(3))
     if self._players[0].death == False:
         while self.dis(pos, bosssphere.center) < bosssphere.radius:
             pos = tuple(
                 self._rand.randIn(self._mapSize - 2 * sphere.radius) +
                 sphere.radius for _ in range(3))
     newSphere = scene.Sphere(pos, sphere.radius)
     self._scene.modify(newSphere, playerId)
     self._players[playerId].nutrientMove = 2
     self._players[playerId].tnutrientMove = 6
     self._changeList.append(
         self.makeChangeJson(playerId, self._players[playerId].aiId, pos,
                             newSphere.radius, 1))
Example #7
0
 def shortAttackDone(self, playerId: int):
     player = self._players.get(playerId)
     if player is None:
         return
     if player.death:
         player.shortAttackCasting = -1
         return
     if player.shortAttackCasting != 0:
         return
     skillLevel = self._players[playerId].skillsLV['shortAttack']
     damage = 500 + 200 * (skillLevel - 1)
     if 1 < skillLevel < 5:
         damage += 100
     attackRange = 1100 + 300 * skillLevel
     if skillLevel == 5:
         attackRange -= 100
     # 创建虚拟球体,找到所有受到影响的物体。受到影响的判定为:相交
     virtualSphere = scene.Sphere(
         self.getCenter(playerId),
         attackRange + self._scene.getObject(playerId).radius)
     for objId in self._scene.intersect(virtualSphere):
         if self._players.get(objId) is not None and objId != playerId:
             newdamage = damage
             if player.dashTime != 0:
                 newdamage *= (1 + (player.skillsLV["dash"] + 2) * 0.1 +
                               0.05)
             if self._players[objId].shieldLevel >= 5:
                 newdamage *= 0.7
             elif self._players[objId].shieldTime != 0:
                 newdamage *= (self._players[objId].skillsLV['shield'] + 2)
                 newdamage /= 10
             self.healthChange(objId, -newdamage)
             self._changeList.append(
                 self.makeSkillHitJson('shortAttack', playerId, objId))
     if skillLevel == 5:
         # self._players[playerId].shieldTime = 30
         self._players[playerId].shieldLevel = 35
         self._changeList.append(self.makeSkillCastJson(playerId, 'shield'))
     player.shortAttackCasting = -1
Example #8
0
    def getFieldJson(self, aiId: int):
        def makeObjectJson(objId,
                           aiId,
                           objType,
                           pos,
                           r,
                           longAttackCasting=-1,
                           shortAttackCasting=-1,
                           shieldTime=-1):
            return '{"id":%d,"ai_id":%d,"type":"%s","pos":[%.10f,%.10f,%.10f],"r":%.10f,"longattackcasting":%d,"shortattackcasting":%d,"shieldtime":%d}' \
                   % (objId, aiId, objType, pos[0], pos[1], pos[2], r, longAttackCasting,shortAttackCasting, shieldTime)

        objectDict = {}
        if aiId == -1:
            for playerId in self._players:
                if self._players[playerId].death:
                    continue
                sphere = self._scene.getObject(playerId)
                objectDict[playerId] = \
                    makeObjectJson(playerId, self._players[playerId].aiId, "player", sphere.center, sphere.radius,
                                   self._players[playerId].longAttackCasting, self._players[playerId].shortAttackCasting,self._players[playerId].shieldTime)
            for objectId in self._objects:
                status = self._objects[objectId]
                sphere = self._scene._objs[objectId]
                objectDict[objectId] = makeObjectJson(objectId, -2,
                                                      status.type,
                                                      sphere.center,
                                                      sphere.radius)
            # 规定营养产生处的ID为4000000+i,该ID暂无意义
            for i, pos in enumerate(self._nutrientFlushPos):
                nutrientId = 4000000 + i
                objectDict[nutrientId] = makeObjectJson(
                    nutrientId, -2, 'source', pos, 0)
        else:
            visionSpheres = [
                scene.Sphere(
                    self._scene.getObject(playerId).center,
                    self._players[playerId].vision +
                    self._scene.getObject(playerId).radius)
                for playerId in self._players.keys()
                if self._players[playerId].aiId == aiId
                and self._players[playerId].death == False
            ]
            visibleLists = [
                self._scene.intersect(vs, False) for vs in visionSpheres
            ]
            for objectId in [i for ls in visibleLists for i in ls]:
                if objectDict.get(objectId) is not None:
                    continue
                sphere = self._scene._objs[objectId]
                if self._players.get(objectId) is not None:
                    objectDict[objectId] = \
                        makeObjectJson(objectId, self._players[objectId].aiId, 'player', sphere.center, sphere.radius,
                                       self._players[objectId].longAttackCasting, self._players[objectId].shortAttackCasting,self._players[objectId].shieldTime)
                else:
                    objType = self._objects.get(objectId).type
                    objectDict[objectId] = makeObjectJson(
                        objectId, -2, objType, sphere.center, sphere.radius)
            for i, pos in enumerate(self._nutrientFlushPos):
                if any(
                        sum((vs.center[i] - pos[i])**2
                            for i in range(3)) < vs.radius**2
                        for vs in visionSpheres):
                    nutrientId = 4000000 + i
                    objectDict[nutrientId] = makeObjectJson(
                        nutrientId, -2, 'source', pos, 0)
        return '{"ai_id":%d,"objects":[%s]}' % (aiId, ','.join(
            objectDict.values()))
Example #9
0
    def update(self):
        # 初始化返回给平台的变化信息的json List
        self._changeList = []
        self._changedPlayer = set()
        if self._time == 5000:
            tempId = 0
            tempMax = 0
            for playerId in self._players:
                if self._players[playerId].aiId == -2:
                    continue
                if self._players[playerId].health > tempMax:
                    tempMax = self._players[playerId].health
                    tempId = self._players[playerId].aiId
            self.gameEnd(tempId, 1)

        # 1、结算技能效果
        for playerId in self._rand.shuffle(list(self._castSkills.keys())):
            if self._gameEnd:
                break
            if self._players.get(playerId) is None:
                continue
            if self._players[playerId].death:
                continue
            skillInfo = self._castSkills[playerId]
            skillName = skillInfo.name
            if skillName == 'shortAttack':
                self.shortAttackSet(playerId)
            elif skillName == 'longAttack':
                self.longAttackSet(playerId, skillInfo.player)
            elif skillName == 'dash':
                self.dash(playerId)
            elif skillName == 'shield':
                self.shield(playerId)
            elif skillName == 'visionUp':
                self.visionUp(playerId)
            elif skillName == 'healthUp':
                self.healthUp(playerId)
        for playerId, player in self._players.items():
            if self._gameEnd:
                break
            if player.death:
                continue
            # 远程攻击蓄力到时间后结算远程攻击效果
            if player.longAttackCasting == 0:
                self.longAttackDone(playerId)
            # 近程攻击蓄力到时间后结算远程攻击效果
            if player.shortAttackCasting == 0:
                self.shortAttackDone(playerId)
            # 冲刺状态时间到后恢复原始速度
            if player.dashTime == 0:
                player.speedLimit = 100
        self._castSkills.clear()

        # 2、移动所有物体(包括玩家,远程子弹,目标生物)
        for playerId, player in self._players.items():
            if self._gameEnd:
                break
            if player.death:
                continue
            if playerId == 0:
                player.speed = tuple(
                    (self._rand.randIn(20 * 1000000) / 1000000) - 10 +
                    self._players[1].speed[x] / 2 +
                    self._players[2].speed[x] / 2 for x in range(3))
            if player.stopTime == 0:
                self.playerMove(playerId)

        # 3、判断相交,结算吃、碰撞、被击中等各种效果
        for playerId in self._rand.shuffle(list(self._players.keys())):
            if self._gameEnd:
                break
            player = self._players.get(playerId)
            if player is None:
                continue
            if player.death:
                continue
            sphere = self._scene.getObject(playerId)
            # 玩家(包括目标生物)可食用的物体对其产生效果,包括食用食饵、营养源、目标生物、以及其他玩家AI
            insideList = self._scene.intersect(sphere, True)
            eatableList = [
                objId for objId in insideList
                if 1.2 * self._scene._objs[objId].radius < sphere.radius
            ]
            for eatenId in eatableList:
                eatenPlayer = self._players.get(eatenId)
                if eatenPlayer is not None:
                    if (eatenPlayer.shieldTime == 0
                            or eatenPlayer.skillsLV["shield"] < 4
                        ) and eatenPlayer.shieldLevel < 5:
                        #self.healthChange(playerId, eatenPlayer.health // 2)
                        #self.healthChange(eatenId, -eatenPlayer.health)
                        self._changeList.append(self.makeDeleteJson(eatenId))
                        if player.aiId == -2:
                            self.gameEnd(1 - eatenPlayer.aiId, 2)
                        else:
                            self.gameEnd(self._players[playerId].aiId, 3)
                    continue
                objType = self._objects[eatenId].type
                if objType == "food":
                    self._changeList.append(self.makeDeleteJson(eatenId))
                    self.healthChange(playerId, 40)
                    self.objectDelete(eatenId)
                    self._foodCount -= 1
                elif objType == "nutrient":
                    self._changeList.append(self.makeDeleteJson(eatenId))
                    player.ability += 5
                    self.nutrientMove(playerId)
                    self.objectDelete(eatenId)
            if playerId == 0:
                continue

            # 玩家接触到的物体对其产生效果,包括受到刺球伤害及子弹伤害
            touchList = self._scene.intersect(sphere, False)
            for touchedId in touchList:
                if self._players.get(touchedId) is not None:
                    continue
                objType = self._objects[touchedId].type
                if objType == "spike":
                    if self._players[playerId].tnutrientMove > 0:
                        self.objectDelete(touchedId)
                        continue
                    if (self._players[playerId].shieldTime == 0
                            or self._players[playerId].skillsLV["shield"] < 5
                        ) and self._players[playerId].shieldLevel < 5:
                        damage = self._players[playerId].health // 3
                        if damage > 2000:
                            damage = 2000
                        self.healthChange(playerId, -damage)
                        self.objectDelete(touchedId)

        # 4、随机产生新的食物等,暂且每回合1个食饵,且上限为1000个。每隔100-110回合刷新一个营养源;
        # 食饵ID为1000000+食物编号, 营养源ID为2000000+营养源位置编号
        if self._time == 0:
            foodPerTick = 150
        else:
            foodPerTick = 10
        for _ in range(foodPerTick):
            if self._gameEnd:
                break
            if self._foodCount > 300:
                break
            center = tuple(self._rand.randIn(self._mapSize) for _ in range(3))
            food = scene.Sphere(center)
            foodId = 1000000 + self._foodCountAll
            self._objects[foodId] = ObjectStatus("food")
            self._scene.insert(food, foodId)
            self._foodCountAll += 1
            self._changeList.append(self.makeChangeJson(foodId, -2, center, 0))
            center2 = tuple(self._mapSize - x for x in center)
            food = scene.Sphere(center2)
            foodId = 1000000 + self._foodCountAll
            self._objects[foodId] = ObjectStatus("food")
            self._scene.insert(food, foodId)
            self._foodCountAll += 1
            self._foodCount += 2
            self._changeList.append(self.makeChangeJson(
                foodId, -2, center2, 0))

        spikenum = 0
        if self._time % 10 == 0:
            spikenum += 1
        for _ in range(spikenum):
            if self._gameEnd:
                break
            if self._spikeCount >= 50:
                break
            center = tuple(self._rand.randIn(self._mapSize) for _ in range(3))
            while self.inplayer(center):
                center = tuple(
                    self._rand.randIn(self._mapSize) for _ in range(3))
            spike = scene.Sphere(center)
            spikeId = 2001000 + self._spikeCountAll
            self._objects[spikeId] = ObjectStatus("spike")
            self._scene.insert(spike, spikeId)
            self._spikeCountAll += 1
            self._spikeCount += 1
            self._changeList.append(self.makeChangeJson(
                spikeId, -2, center, 0))

        if self._nutrientFlushTime == 0:
            pos = self._rand.randIn(len(self._nutrientFlushPos) >> 1) << 1
            nutrientId1 = int(2000000 + pos)
            nutrientId2 = int(2000000 + pos + 1)
            time = 0
            while (self._objects.get(nutrientId1)
                   is not None) and (self._objects.get(nutrientId2)
                                     is not None):
                pos = self._rand.randIn(len(self._nutrientFlushPos) >> 1) << 1
                nutrientId1 = int(2000000 + pos)
                nutrientId2 = int(2000000 + pos + 1)
                time += 1
                if time > 10:
                    break
            if time <= 10:
                if self._objects.get(nutrientId1) is None:
                    nutrient = scene.Sphere(self._nutrientFlushPos[pos])
                    self._objects[nutrientId1] = ObjectStatus("nutrient")
                    self._scene.insert(nutrient, nutrientId1)
                if self._objects.get(nutrientId2) is None:
                    nutrient = scene.Sphere(self._nutrientFlushPos[pos + 1])
                    self._objects[nutrientId2] = ObjectStatus("nutrient")
                    self._scene.insert(nutrient, nutrientId2)
                self._nutrientFlushTime = self._rand.randIn(100) + 10
        else:
            self._nutrientFlushTime -= 1

        # 5、时间+1
        # 所有技能冷却时间 -1, 护盾持续时间 -1, 营养源刷新时间 -1, 瞬移发动后时间 +1
        self._time += 1
        for playerId, player in self._players.items():
            if self._gameEnd:
                break
            if player.death:
                continue
            if player.shieldTime > 0:
                player.shieldTime -= 1
                if player.skillsLV['shield'] > 2 and player.skillsLV[
                        'healthUp'] == 5:
                    self.healthChange(playerId,
                                      5 * player.skillsLV['shield'] - 5)
            if player.shieldLevel > 0:
                player.shieldLevel -= 1
            if player.stopTime > 0:
                player.stopTime -= 1
            if player.longAttackCasting > 0:
                player.longAttackCasting -= 1
            if player.shortAttackCasting > 0:
                player.shortAttackCasting -= 1
            if player.dashTime > 0:
                player.dashTime -= 1
            if player.nutrientMove > 0:
                player.nutrientMove -= 1
            if player.tnutrientMove > 0:
                player.tnutrientMove -= 1
            for skillName in self._players[playerId].skillsCD.keys():
                if player.skillsCD[skillName] > 0:
                    player.skillsCD[skillName] -= 1

        for playerId in self._players:
            if self._players[playerId].death == False:  # 确保只生成未死亡的玩家的变化信息
                self._changeList.append(self.newMakePlayerJson(playerId))

        #判断是否为测试赛
        if self._gameType != 0:
            #测试赛1,如果选手移动则成功
            if (self._gameType == 1):
                for playerId in self._players:
                    if (self._players[playerId].aiId != 0):
                        continue
                    if self._players[playerId].speed != (0, 0, 0):
                        self.testGameEnd(10)

        # 调用回调函数,向平台传回变化信息
        self._callback("[" + ",".join(self._changeList) + "]")