Tải bản đầy đủ (.docx) (16 trang)

Trí tuệ nhân tạo robocode tournament

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (428.82 KB, 16 trang )

TRƯỜNG ĐẠI HỌC BÁCH KHOA TP.HỒ CHÍ MINH
KHOA KHOA HỌC KỸ THUẬT VÀ MÁY TÍNH
────────────── * ─────────────

BÀI TẬP LỚN 2
MÔN: TRÍ TUỆ NHÂN TẠO

ROBOCODE TOURNAMENT
Nhóm robocode:
Nhóm thực hành:
Giáo viên hướng dẫn:

PhướcKhoa
A02-BA
NGUYỄN HỮU THỊNH

TP.HỒ CHÍ MINH, tháng 5 năm 2015

1


MỤC LỤC

2


I.GIỚI THIỆU VỀ ROBOCODE
Robocode là một chương trình trò chơi mà mục tiêu là tạo ra một robot, các
robot mô phỏng xe tăng trong một đấu trường chiến đấu để tìm và cạnh tranh với
các robot khác, nó được trang bị với hệ thống radar. Một robot có thể di chuyển
tới, lui ở các tốc độ khác nhau và di chuyển qua trái, qua phải. Các radar và


tháp pháo có thể được chuyển sang trái hoặc sang phải độc lập với nhau so với
phần còn lại của xe tăng. Khẩu súng có thể bắn. Khi cài đặt một trận đấu, ta có thể
xem được trận đấu từ bên ngoài màn hình chơi hoặc dùng máy tính mô phỏng trận
đấu mà không cần hiển thị đồ họa. Người chơi là các lập trình của robot, những
người này sẽ không ảnh hưởng trực tiếp vào trò chơi mà thay vào đó người chơi
phải lập trình làm sao cho robot thông minh có thể xử lý và phản ứng tất cả các sự
kiện xảy ra trong lĩnh vực chiến đấu. Khi một robot đối thủ lọt vào rađa, một sự
kiện sẽ được sinh ra và một hành động phù hợp sẽ được robot thực hiện. Robot có
thể lấy được các thông tin về một đối thủ đang trong vùng quét của ra đa như tốc
độ, heading, năng lượng còn lại, tên và gốc giữa heading của nó với robot đối thủ,
khoảng cách giữa nó với đối thủ. Dựa vào các thông tin này mà rô bốt sẽ đưa ra các
hành động phù hợp. Ví dụ, khi phát hiện một đối thủ trong vòng rađa, robot có thể
dùng súng để bắn. Các robot có thể ra trận cùng với đội robot của nó. Bằng việc
giao tiếp với các robot khác, chúng có thể trao đổi các thông tin như nơi có đối thủ
được phát hiện và dựa trên chiến lược được chọn, một robot có thể chạy trốn từ
đám các đối thủ hoặc thông báo tin cho các đồng minh của nó về thông tin các đối
thủ đó. Các robot được viết bằng ngôn ngữ lập trình Java và các trò chơi Robocode
có thể chạy trên bất kỳ hệ điều hành được hỗ trợ bởi các nền tảng Java, bao gồm tất
cả các hệ thống phổ biến như Windows, Mac OS X, Linux etc.
Chiến trường Robocode là nơi mà tất cả các trận đấu diễn ra. Mỗi điểm có
tọa độ x là tọa độ theo chiều ngang và y là tọa độ theo chiều dọc cặp tọa độ này sẽ
thay đổi tùy theo vị trí của chiến trường. Vị trí ban đầu (0, 0) của chiến trường
được đặt ở dưới cùng bên trái của chiến trường, một tọa độ (x, y) trên chiến trường
luôn luôn là một cặp số thực dương.

3


0
270


(getBattleFieldWidth(),
 getBattleFieldHeight())

90
(0,0)

180

II.HIỆN THỰC
Robot của nhóm sử dụng kế thừa từ lớp AdvancedRobot.

1.CÁC PHƯƠNG THỨC JAVADOC TỪ MÃ NGUỒN
ROBOCODE:
setAdjustGunForRobotTurn(independent):
Thiết lặp cho súng quay độc lặp với thân robot,nếu independent=true thì súng
sẽ quay độc lặp với thân và ngược lại.
- setAdjustRadarForGunTurn(independent):
Thiết lặp cho Radar quay độc lặp với súng robot,nếu independent=true thì radar
sẽ quay độc lặp với súng và ngược lại.
- setAdjustRadarForRobotTurn(independent):
Thiết lặp cho Radar quay độc lặp với thân robot,nếu independent=true thì radar
sẽ quay độc lặp với thân và ngược lại.
-

4


setColors(Color bodyColor, Color gunColor, Color radarColor, Color
bulletColor, Color scanArcColor)

Thiết lặp màu sắc cho các bộ phận trên robot các bộ phận gôm:thân
robot,súng,radar,đạn,vùng radar quét.
- getX(): Lấy tọa độ X của robot.
- getY(): Lấy tọa độ Y của robot.
- getBattleFieldWidth(): Lấy kích thước chiều ngang của chiến trường (màn)
- getBattleFieldHeight(): Lấy kích thước chiều cao của chiến trường (màn)
Ghi chú: Thường kích thước chiến trường mặc định là 800x600
- setTurnRadarRight(degree):Thiệt lặp cho radar quay bên phải với một góc
là degree. Degree nằm từ 0->360 độ. Nếu degree là số âm thì
setTurnRadarRight đổi thành setTurnRadarLeft.
- getRadarTurnRemaining(): Kiểm tra xem radar có quay không!Nếu không
quay thì có thể thực hiện hành động quay như trình bày ở trên
- execute(): thực thi các lệnh trong đã đưa ra trong vòng lặp while(true)
- getEnergy():Lấy năng lượng hiện tại của robot mình.
- getHeading(): Lấy góc của body robot mình,hình bên dưới mô tả giá trị của
bodyHeading.
-

getGunHeading(): Lấy góc của súng robot mình,giá trị nằm trong khoảng
tương tự như getHeading().
- getRadarHeading(): Lấy góc của radar robot mình, giá trị nằm trong khoảng
tương tự như getHeading().
- getVelocity(): Lấy vận tốc hiện tại của robot mình.
- setAhead(distance):Điều khiển robot đi thẳng với khoảng cách distance có
kiểu double
-

5



setBack(distance):Điều khiển robot đi lùi với khoảng cách distance có kiểu
double
- setTurnRight(rotate):Điều khiển body của robot xoay bên phải với góc
rotate có kiểu double ,rotate nhận giá trị là độ.
- setTurnGunRight(rotate): ):Điều khiển súng của robot xoay bên phải với
góc rotate có kiểu double ,rotate nhận giá trị là độ.
- setFire(power): Thiết lặp bắn đạn cho robot,với viên đạn có kích thước là
power.Power nằm trong khoảng 0.1<=power<=3.0
-

Trong ScannedRobotEvent e:
e.getBearing() có giá trị từ:
180<=e.getBearing()<=180
-

Nếu robot đối phương nằm bên trái của robot bạn thì getBearing() sẽ là số
âm (0->-180) .Ngược lại nếu robot đối phương nằm bên phải robot thì
e.getBearing() sẽ là số dương (0->180)
Lưu ý : so sánh robot đối phương nằm bên trái hay phải phụ thuộc vào
bodyHeading (getHeading()),có nghĩa là bodyHeading() làm chuẩn .Rồi xét
robot bên trái hay bên phải)
e.getHeading(): Lấy góc của body robot đối phương.
e.getDistance(): Lấy khoảng cách giữa mình và đối phương.
e.getVelocity(): Lấy vận tốc của đối phương.
onScannedRobot(ScannedRobotEvent event) sự kiện xảy ra khi radar quét
trúng đối thủ
- onHitWall(HitWallEvent event) sự kiện xảy ra khi va vào tường
- onWin(WinEvent event) sự khiện xảy ra khi thắng
-


2.CÁC PHƯƠNG THỨC MÀ NHÓM TỰ TẠO.
a. Phương thức bắn đối phương khi gần khoảng cách tầm 150 trở
lại.
- Bước 1: Lấy góc giữa nồng súng của mình và hướng của đối phương.
6


double bearingFromGun = normalRelativeAngleDegrees(phi1 getGunHeading());
- Bước 2: Xoay nồng súng qua.
setTurnGunRight(bearingFromGun);
- Bước 3: Bắn.
setFire(power);
- Dưới đây là đoạn code mô tả cho metho trên:
public void setFireXForNear(double power, double phi1, double
getGunHeadingMe) {
double bearingFromGun = normalRelativeAngleDegrees(phi1 getGunHeading());
setTurnGunRight(bearingFromGun);
if (getGunHeat() == 0) {
setFire(power);
}
}
b. Phương thức bắn đối phương có tiên đoán trước điểm đến.
public void setFireX(double power, double egetVelocity, double
distance, double eHeading, double phi1)
=> Phần này sẽ được trình bày rõ hơn ở bên dưới về cách thức thực
hiện ,cũng như việc tính toán chi tiết ,tỷ mỹ.

7



3.CÁC KIẾN THỨC MÀ NHÓM SỬ DỤNG.
Bao gồm kiến thức TOÁN HỌC và kiến thức môn AI.
- Kiến thức toán học : là thực hiện việc tính toán các khoảng
cách,điểm…v…v…
- Kiến thức AI áp dụng là : Lập kế hoạch.
Đó chính là cho trạng thái khởi đầu và trạng thái mục tiêu (thể hiện
ở việc tiên đoán điểm đến của đối phương và điểm đến của đạn đối
phương) ,sau một chuỗi các tính toán dựa trên kiến thức toán học ,để
chuyển đến các hành động tương ứng ,sao cho đến được trạng thái mục
tiêu từ trạng thái khởi đầu.
Ví dụ:
-

Dự đoán điểm đến của đối phương.

Trạng thái khởi đầu :Vị trí,góc… của mình và đối phương
Trạng thái mục tiêu: Điểm đến của đối phương
-

Dự đoán điểm đến của đạn đối phương.

Trạng thái khởi đầu :Vị trí,góc… của mình và đối phương
Trạng thái mục tiêu: Điểm đến viên đạn của đối phương
=> Phần này sẽ được trình bày rõ hơn ở bên dưới về cách thức thực
hiện ,cũng như việc tính toán chi tiết ,tỷ mỹ.

8


4. TÍNH TOÁN TỌA ĐỘ ĐỐI PHƯƠNG.


Hình 1
Theo hình 1 ta có:
X1= e.getDistance()*cos(apha)=e.getDistance()*sin(absoluteBearing).
Y1= e.getDistance()*sin(apha)=e.getDistance()*cos(absoluteBearing).
Với alpha = 90-(e.getBearing()+getHeading()).
absoluteBearing = e.getBearing+getHeading().
=> Như đã thấy, giá trị X1 hoặc Y1 ta có thể tính theo alpha hoặc absoluteBearing.
Vì theo tính chất ta có :
cos(a)=sin(90-a)
sin(a)=cos(90-a).
Từ đây suy ra tọa độ đối phương là: (Position of Enemy)
X= getX()+X1.
Y=getY()+Y1
9


5.DỰ ĐOÁN ĐIỂM ĐẾN CỦA ĐỐI PHƯƠNG

Hình 2
- Dựa vào hình ta thấy dX0 và dY0 sau khi tính được là:
θ1:90-(e.getBearing()+e.getHeading());
dX0=e.getBearing()*cos(θ1).
dY0=e.getBearing()*sin(θ1).
- Tương tự dựa vào hình 2 ta xét tam giác ABC vuông tại B ta cũng có :
θ2: 90-e.getBearing();
dXem=Vem.t.cos(θ2).
dYem=Vem.t.sin(θ2).
Vem=e.getVelocity(). // Đây chính là vận tốc của đối phương di chuyển.
- Ở đây t là thời gian ta cần tìm ,để với vận tốc đó và thời gian t như vậy thì đối

phương sẽ di chuyển đến điểm như thế nào?
- Ta xét tiếp tam giác MDC vuông tại D.Ta có:
MD2+DC2=MC2 (1)
Với MD=dX1=dX0+dXem.
Và CD=dY1=dY0+dYem.
10


MC=Vbt.t
-Vbt chính là vận tốc của đạn chúng ta bắn.Theo luật robocode ta có:
Vbt=20-3*power.
Power ở đây chính là năng lượng đạn mà chúng ta sẽ bắn ra ,chính là phần
tử được truyền vào hàm setFire(power) hay fire(power) .
Thay các giá trị MD,MC,DC vào (1) ta được:
(Vbt.t)2=(dX0+dXem)2+(dY0+dYem)2.
Vbt2.t2-(dX0+dXem)2-(dY0+dYem)2=0.
Vbt2.t2-(dX0+ Vem.t.cos(θ2))2-(dY0+ Vem.t.cos(θ2))2=0
[Vbt2-Vem2.cos2(θ2)-Vem2.sin2(θ2)].t2+[-2dX0.Vem.cos(θ2)-2dY0.Vem.sin(θ2)].t+
(-dX02-dY02). (*)
- Theo lý thuyết toán học ta có:
at2+bt+c = 0
delta = b2-4ac.
- Nếu delta0 thì phương trình có 2 nghiệm là :
t=
- Áp dụng vào phương trình (*) ta có:
b=+[-2dX0.Vem.cos(θ2)-2dY0.Vem.sin(θ2)].
a=[Vbt2-Vem2.cos2(θ2)-Vem2.sin2(θ2)].
c=(-dX02-dY02)
- Hiện thực trên code cho ý tưởng trên như sau:
double Vem = egetVelocity;

double Vbt = 20 - 3 * power;
double phi2 = Math.toRadians(eHeading);
double phi1 = Math.toRadians(getHeading() + e.getBearing());
double dx = distance * Math.sin(phi1);
11


double dy = distance * Math.cos(phi1);
double A = Math.pow(Vbt, 2) - Math.pow(Vem, 2);
double B = -2 * dx * Vem * Math.sin(phi2) - 2 * dy * Vem * Math.cos(phi2);
double C = -Math.pow(dx, 2) - Math.pow(dy, 2);
double D = B * B - 4 * A * C;
double t1, t2, t;
if (D >= 0) {
t1 = (-B + Math.sqrt(D)) / (2 * A);
t2 = (-B - Math.sqrt(D)) / (2 * A);
t = Math.max(t1, t2);
} else {
t = 0;
}
double dxem = Vem * t * Math.sin(phi2);
double dyem = Vem * t * Math.cos(phi2);
double dx1 = dx + dxem;
double dy1 = dy + dyem;
//For gun
double degree = 90 - Math.toDegrees(Math.atan2(dy1, dx1)) getGunHeading();
degree = normalRelativeAngleDegrees(degree);
setTurnGunRight(degree);
//Bullet
setFire(power);


12


6. DỰ ĐOÁN ĐẠN CỦA ĐỐI PHƯƠNG.

Hình 3
Tương tự phần dự đoán điểm di chuyển của đối phương ta có:
(Vb.t)2=X2+Y2 (2)
Vb chính là vận tốc đạn của đối phương. Câu hỏi đặt ra làm thế nào ta sẽ lấy
được thông số của nó? Như ta biết :
Vb=20-3.power
Vậy làm sao để có năng lượng viên đạn bắn của đối phương ? Ta sẽ dùng 1
biến để lưu năng lượng trước đó của đối phương,và ta sẽ lấy năng lượng trước đó
trừ đi năng lượng hiện tại mà đối phương đang có ta sẽ có được năng lượng của
viên đạn.Ban đầu lastEnergyOfEnemy luôn luôn bằng 100.
double lastEnergyOfEnemy = 100;
double newEnergyOfEnemy.
Nếu trường hợp đối phương không bắn đạn thì giá trị năng lượng trước và
năng lượng sau của đối phương là như nhau,trong trường hợp đó ta di chuyển tùy
theo ý thích hoặc có thể không di chuyển ,vì đối phương không băn đạn.
13


Nêu trường hợp năng lượng hiện tại của đối phương lớn hơn năng lượng
trước đó có được ( có nghĩa là robot đối phương được cộng thêm năng lượng do
bắn trúng được mình ) hoặc năng lượng hiện tại cộng thêm max năng lượng của
power vẫn nhỏ hơn năng lượng lúc sau,có nghĩa là đối phương có thể bị va tường,
thì lúc đó ta cần cập nhật lại hai biến như sau:
if ((this.newEnergyOfEnemy >= this.lastEnergyOfEnemy)

|| (this.newEnergyOfEnemy + Rules.MAX_BULLET_POWER <
this.lastEnergyOfEnemy)) {
this.lastEnergyOfEnemy = this.newEnergyOfEnemy;
}
}
- Ta lại có:
X=X1+X0.
Y=Y1+Y0.
θ1:90-(e.getBearing()+e.getHeading()); (tương tự như phần trên)
d=e.getDistance() //Khoảng cách giữa ta và đối phương
V=getVelocity() //Vận tốc của robot ta di chuyển.
Với
X1=d*cos(θ1).
Y1=d*sin (θ1).
θ2=90-getHeading().
X2=V.t.cos(θ2).
Y2=V.t.sin(θ2).
 (Vb.t)2=(d.cos(θ1)+v.t.cos(θ2))2+(d.sin(θ1)+vtsin(θ2))2
 (Vb.t)2=d2+V2t2+2.d.v.t.(sin(θ1)sin(θ2)+cos(θ1)cos(θ2))
 (Vb2-V2)t2+[-2.d.v(sin(θ1).sin(θ2)+cos(θ1).cos(θ2))].t-d2=0

- Theo lý thuyết toán học ta có:
 at2+bt+c = 0
 delta = b2-4ac.

- Nếu delta0 thì phương trình có 2 nghiệm là :
14

(**)



 t=

- Áp dụng vào phương trình (**) ta có:
b=[-2.d.v(sin(θ1).sin(θ2)+cos(θ1).cos(θ2))]
a=(Vb2-V2).
c=-d2
- Hiện thực trên code cho ý tưởng trên như sau:
powerOfBullet = this.lastEnergyOfEnemy - e.getEnergy();
if (powerOfBullet >= 0.1 && powerOfBullet <= 3.0) {
double Vb = 20 - 3 * powerOfBullet;
double V = getVelocity();
double A = Vb * Vb - V * V;
double d = e.getDistance();
double B = -2 * d * V * (Math.sin(phi1) *
Math.sin(getHeadingRadians()) + Math.cos(phi1) *
Math.cos(getHeadingRadians()));
double C = -d * d;
double delta = B * B - 4 * A * C;
double time;
if (delta >= 0) {
double t1 = -B + Math.sqrt(delta) / (2 * A);
double t2 = -B + Math.sqrt(delta) / (2 * A);
time = Math.max(t1, t2);
} else {
time = 0;
}
double xt = V * time * Math.sin(getHeadingRadians()) + getX();
//proposed x position of impact
double yt = V * time * Math.cos(getHeadingRadians()) + getY();

//proposed y position of impact
go(Math.atan2((yt - getY()), (xt - getX())), this.move,
getHeadingRadians());
}

15


III.TÀI LIỆU THAM KHẢO
/>
16



×