Управление группой мобильных объектов

Автор работы: Пользователь скрыл имя, 26 Февраля 2013 в 06:52, курсовая работа

Описание работы

Данная курсовая работа посвящена разработке алгоритма интеллектуального управления танком для участия в конкурсе «Российский кубок по программированию искусственного интеллекта CodeTanks 2012 (Russian AI Cup)». В работе рассмотрены принципы наиболее эффективного поведения танка, позволяющие ему эффективно передвигаться по полю, минимизировать повреждения от танков оппонентов и набирать как можно большее количество очков за счет уничтожения танков оппонентов. Алгоритм реализован на языке программирования Python 2.7.3 в среде разработки JetBrains PyCharm 2.6.3.

Содержание работы

Введение 3
1 О мире CodeTanks 2012 4
1.1Общие положения и правила 4
1.2 Описание игрового мира 5
1.3 Описание танков 7
1.4 Описание снарядов и механики попаданий 9
1.5 Описание бонусов 10
1.6 Начисление баллов 11
2 Стратегия управления танком 12
2.1 Выбор танка 12
2.2 Принципы поведения танка 14
2.2.1 Движение танка 15
2.2.1.1 Уворот 19
2.2.1.2 Рикошет 20
2.2.2 Стрельба 22
Заключение 24
Список использованной литературы 25
Приложение А 26

Файлы: 1 файл

kur.docx

— 3.01 Мб (Скачать файл)

        PLAYER_CONTEXT = 5

        MOVES = 6

 

Модуль Runner.py

import sys

from MyStrategy import MyStrategy

from RemoteProcessClient import RemoteProcessClient

from model.Move import Move

 

class Runner:

    def __init__(self):

        if sys.argv.__len__() == 4:

            self.remote_process_client = RemoteProcessClient(sys.argv[1], int(sys.argv[2]))

            self.token = sys.argv[3]

        else:

            self.remote_process_client = RemoteProcessClient("localhost", 31000)

            self.token = "0000000000000000"

 

    def run(self):

        try:

            self.remote_process_client.write_token(self.token)

            team_size = self.remote_process_client.read_team_size()

 

            strategies = []

            tank_types = []

 

            for strategy_index in xrange(team_size):

                strategy = MyStrategy()

                strategies.append(strategy)

                tank_types.append(strategy.select_tank(strategy_index, team_size))

 

            self.remote_process_client.write_selected_tanks(tank_types)

 

            while True:

                player_context = self.remote_process_client.read_player_context()

                if player_context is None:

                    break

 

                player_tanks = player_context.tanks

                if player_tanks.__len__() != team_size:

                    break

 

                moves = []

 

                for strategy_index in xrange(team_size):

                    move = Move()

                    moves.append(move)

                    strategies[strategy_index].move(player_tanks[strategy_index], player_context.world, move)

 

                self.remote_process_client.write_moves(moves)

        finally:

            self.remote_process_client.close()

 

Runner().run()

 

 

Модуль TankMedium.py

__author__ = 'Drell'

 

from math import *

from model.FireType import FireType

from model.TankType import TankType

from model.Unit import Unit

from Head import Head

from Dodge import Dodge

from Calculation import Calculation

 

class TankMedium:

    def __init__(self):

        self.target = None

        self.phase = -1

        self.quarter = 0

        self.angle = 0

        self.head = Head()

        self.dodge = Dodge()

        self.stuckCounter = 0

        self.unstuckCounter = 0

 

        self.closeToBorderCounter = 0

        self.borderland = False

        self.borderlandCounter = 0

        self.plannedAngle = 0

 

    def selectQuarter(self, me, move):

        if me.x < 640 and me.y < 400:

            self.quarter = 1

            self.angle = pi/4

        elif me.x <= 640 and me.y >= 400:

            self.quarter = 2

            self.angle = -pi/4

        elif me.x > 640 and me.y > 400:

            self.quarter = 3

            self.angle = -3*pi/4

        else:

            self.quarter = 4

            self.angle = 3*pi/4

        self.plannedAngle = self.angle

        self.phase += 1

 

    def rotateToAngle(self, me, move):

        DiffAngle = self.angle - me.angle

        if DiffAngle > pi:

            DiffAngle = pi - DiffAngle

        elif DiffAngle < -pi:

            DiffAngle = -pi - DiffAngle

        #        print 'Diff ' + str(DiffAngle) + ' target ' + str(self.angle) + ' my ' + str(me.angle)

        if DiffAngle > 0:

            move.left_track_power = me.engine_rear_power_factor

            move.right_track_power = -1

        if DiffAngle < 0:

            move.left_track_power = -1 #MoveSpeed#me.engine_rear_power_factor

            move.right_track_power = me.engine_rear_power_factor

 

    #TODO SPEED UP DIS SHIT

    def BackToXY(self, me, x, y, move):

        angletoXY = me.get_angle_to(x, y)

        if angletoXY < 0 and angletoXY > -pi + pi/6:

            move.left_track_power = me.engine_rear_power_factor

            move.right_track_power = -1

        elif angletoXY > 0 and angletoXY < pi - pi/6:

            move.left_track_power = -1 #MoveSpeed#me.engine_rear_power_factor

            move.right_track_power = me.engine_rear_power_factor

        else:

            move.left_track_power = -1

            move.right_track_power = -1

        if (abs(me.x - x) < me.width/2) and (abs(me.y - y) < me.width/2):

            self.phase += 1

 

    def movetoUnit(self, me, unit, move):

        angletoUnit = me.get_angle_to_unit(unit)

        self.plannedAngle = angletoUnit

        #        if me.x < 50 or me.y < 50 or me.x > 1230 or me.y > 750 or me.get_distance_to_unit(unit) < 100 or self.borderland :

        #        if not self.borderland:

        #            self.borderland = True

        #            self.borderlandCounter = 20

        #if (abs(angletoUnit) >= pi/2 and me.get_distance_to_unit(unit) < 200) or (abs(angletoUnit) >= 2*pi/3 and me.get_distance_to_unit(unit) < 400):

        if (abs(angletoUnit) >= pi/2 and me.get_distance_to_unit(unit) < 400):

            if 0 > angletoUnit > -5*pi/6:

                move.left_track_power = 1#me.engine_rear_power_factor

                move.right_track_power = -1

            elif 0 <= angletoUnit < 5*pi/6:

                move.left_track_power = -1

                move.right_track_power = 1#me.engine_rear_power_factor

            elif angletoUnit > 0:

                move.left_track_power = -1

                move.right_track_power = -cos(angletoUnit)*cos(angletoUnit)

            else:

                move.left_track_power = -cos(angletoUnit)*cos(angletoUnit)

                move.right_track_power = -1

        else:

            if angletoUnit < -pi/6:

                move.left_track_power = -1

                move.right_track_power = 1#me.engine_rear_power_factor

            elif angletoUnit > pi/6:

                move.left_track_power = 1#me.engine_rear_power_factor

                move.right_track_power = -1

            elif angletoUnit > 0:

                move.left_track_power = 1

                move.right_track_power = cos(angletoUnit)*cos(angletoUnit)

            else:

                move.left_track_power = cos(angletoUnit)*cos(angletoUnit)

                move.right_track_power = 1

            #        else:

            #            if (abs(angletoUnit) >= pi/2 and me.get_distance_to_unit(unit) < 100) or (abs(angletoUnit) >= 2*pi/3 and me.get_distance_to_unit(unit) < 200):

            #                if 0 > angletoUnit > -5*pi/6:

            #                    move.left_track_power = 0

            #                    move.right_track_power = -1

            #                elif 0 <= angletoUnit < 5*pi/6:

            #                    move.left_track_power = -1

            #                    move.right_track_power = 0

            #                else:

            #                    move.left_track_power = -1

            #                    move.right_track_power = -1

            #            else:

            #                if angletoUnit < -pi/6:

            #                    move.left_track_power = 0

            #                    move.right_track_power = 1

            #                elif angletoUnit > pi/6:

            #                    move.left_track_power = 1

            #                    move.right_track_power = 0

            #                else:

            #                    move.left_track_power = 1

            #                    move.right_track_power = 1

 

 

            #       radial movement. Temporary useless

            #            x2, y2 = unit.x, unit.y

            #            angle = me.get_angle_to(x2, y2)

            #            r = me.get_distance_to(x2, y2) / (2 * cos(pi/2 - me.angle + angle))

            #            if 0 > angle > -pi/2:

            #                move.right_track_power = (me.width/-2.0 + abs(r))/(me.width/2.0 + abs(r))

            #                move.left_track_power = 1

            #            elif 0 < angle < pi/2:

            #                move.right_track_power = 1

            #                move.left_track_power = (me.width/-2.0 + abs(r))/(me.width/2.0 + abs(r))

 

 

    def takeBonus(self, me, world, move):

    #        if self.borderland:

    #            self.borderlandCounter -= 1

    #        if self.borderlandCounter < 0:

    #            self.borderland = False

        if len(world.bonuses) > 0:

            self.movetoUnit(me, min(world.bonuses, key=lambda a: a.get_distance_to_unit(me)), move)

 

    def getShellList(self, world, me):

        shellList = []

        for shell in world.shells:

            interrupted = False

            myrange, pt = self.dodge.hits(shell, me)

            if myrange == 6666:

                continue

            for obstacle in world.obstacles:

                obstRange, pt = self.dodge.hits(shell, obstacle)

                if 0 < obstRange < myrange:

                    interrupted = True

                    break

            if not interrupted:

                for bonus in world.bonuses:

                    obstRange, pt = self.dodge.hits(shell, bonus)

                    if 0 < obstRange < myrange:

                        interrupted = True

                        break

            if not interrupted:

                for tank in world.tanks:

                    if tank.player_name == 'Yokree':

                        continue

                    obstRange, pt = self.dodge.hits(shell, tank)

                    if 0 < obstRange < myrange:

                        interrupted = True

                        break

            if not interrupted:

                shellList.append(shell)

        return shellList

 

    def move(self, me, world, move):

        #detecting position

        if self.phase == -1:

            self.selectQuarter(me, move)

 

        #taking your corner

        if self.phase == 0:

            if me.crew_health < (me.crew_max_health / 4) or me.hull_durability < (me.hull_max_durability / 4):

                self.phase = 2

 

            if self.quarter == 1:

                self.BackToXY(me, me.width/2, me.width/2, move)

            if self.quarter == 2:

                self.BackToXY(me, me.width/2, 800-me.width/2, move)

            if self.quarter == 3:

                self.BackToXY(me, 1280 - me.width/2, 800 - me.width/2, move)

            if self.quarter == 4:

                self.BackToXY(me, 1280 - me.width/2, me.width/2, move)

 

            #            if abs(me.speedX) < 0.1 and abs(me.speedY) < 0.1:

            #                self.stuckCounter += 1

 

            #            if self.stuckCounter > 150:

            #                self.phase = 2

 

        #rotating 45 degree to corner and holding position

        if self.phase == 1:

 

            if me.crew_health < (me.crew_max_health / 3) or me.hull_durability < (me.hull_max_durability / 4):

                self.phase = 2

 

            shellList = self.getShellList(world, me)

            dodgeableShellsList = []

 

            if len(shellList) > 0:

                for shell in shellList:

                    dodgeable, l, r = self.dodge.moveToDodge(me, shell, move)

                    if dodgeable:

                        dodgeableShellsList.append(shell)

                if len(dodgeableShellsList) > 0:

                    d, l, r = self.dodge.moveToDodge(me, max(dodgeableShellsList, key=lambda a: a.get_distance_to_unit(me)), move)

                    if d:

                        move.left_track_power = l

                        move.right_track_power = r

                    else:

                        self.dodge.rotateToDodge(me, min(shellList, key=lambda a: a.get_distance_to_unit(me)), move)

                self.dodge.rotateToDodge(me, min(shellList, key=lambda a: a.get_distance_to_unit(me)), move)

            else:

                self.rotateToAngle(me, move)

 

            tanks_alive = 0

            for tank in world.tanks:

                if tank.crew_health > 0 and tank.hull_durability > 0:

                    tanks_alive += 1

            if tanks_alive <= 4:

                self.phase += 1

 

        #takin da bonuses and dodging da shells

        if self.phase == 2:

            shellList = self.getShellList(world, me)

            dodgeableShellsList = []

            if len(shellList) > 0:

                for shell in shellList:

                    dodgeable, l, r = self.dodge.moveToDodge(me, shell, move)

                    if dodgeable:

                        dodgeableShellsList.append(shell)

 

            if len(dodgeableShellsList) > 0:

                d, l, r = self.dodge.moveToDodge(me, max(dodgeableShellsList, key=lambda a: a.get_distance_to_unit(me)), move)

                if d:

                    move.left_track_power = l

                    move.right_track_power = r

                else:

                    self.takeBonus(me, world, move)

            else:

                self.takeBonus(me, world, move)

 

            #            if len(world.shells) > 0:

            #                dist, pt = self.dodge.hits(world.shells[0], me)

            #                if dist != 6666:

            #                    if not self.dodge.moveToDodge(me, world.shells[0], move):

            #                        self.takeBonus(me, world, move)

            #                else:

            #                    self.takeBonus(me, world, move)

            #            else:

            #                self.takeBonus(me, world, move)

 

            # HEAD:

        self.head.move(me, world, move)


Информация о работе Управление группой мобильных объектов