Автор работы: Пользователь скрыл имя, 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
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[
self.token = sys.argv[3]
else:
self.remote_process_client = RemoteProcessClient("
self.token = "0000000000000000"
def run(self):
try:
self.remote_process_client.
team_size = self.remote_process_client.
strategies = []
tank_types = []
for strategy_index in xrange(team_size):
strategy = MyStrategy()
strategies.append(strategy)
tank_types.append(strategy.
self.remote_process_client.
while True:
player_context = self.remote_process_client.
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].
self.remote_process_client.
finally:
self.remote_process_client.
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_
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_
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(
else:
move.left_track_power = -cos(angletoUnit)*cos(
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(
else:
move.left_track_power = cos(angletoUnit)*cos(
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(
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(
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[
# 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)