-
Notifications
You must be signed in to change notification settings - Fork 0
/
robot_weapons.py
116 lines (99 loc) · 4.43 KB
/
robot_weapons.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
"""
Handle weapon detection
"""
from Framework.interface import IDamageable
from Items import weapons
import Framework.message as message
import random
from dataclasses import replace
class RobotWeapons:
def __init__(self, game):
self.game = game
self.battlefield = game.battlefield
def shoot_straight_weapon(self, x: int, y: int, weapon: weapons.StraightWeapon) -> str:
"""
Fire the weapon from (x, y) at a given direction. The weapon deals
certain damage to the target hit
:param x: the x-coordinate of starting point
:param y: the y-coordinate of the starting point
:param weapon: the weapon used
:return: the target hit by the weapon
"""
# generate sound and heat at starting position
self.battlefield.generate_sound(x, y, weapon.config.sound_emission)
self.battlefield.generate_heat(x, y, weapon.config.heat_emission)
# set shooting direction
dx, dy = 0, 0
px, py = x, y
if weapon.direction == message.UP:
dy = -1
elif weapon.direction == message.DOWN:
dy = 1
elif weapon.direction == message.LEFT:
dx = -1
elif weapon.direction == message.RIGHT:
dx = 1
distance = 1
# initial displacement
px += dx
py += dy
damage = weapon.config.damage
accuracy = weapon.config.accuracy
# find the first target hit
while not self.battlefield.is_occupied(px, py):
px += dx
py += dy
accuracy -= weapon.config.accuracy_decay # reduce weapon accuracy through distance
distance += 1
if distance >= weapon.config.range:
break
# prevent out-of-bound index
px = max(0, min(px, len(self.battlefield.field[0]) - 1))
py = max(0, min(py, len(self.battlefield.field) - 1))
# prevent hitting player itself
if px == x and py == y:
return 'weapon missed!'
# deals damage to the target
occupant = self.battlefield.get_grid(px, py).get_occupant()
if isinstance(occupant, IDamageable):
print(self.battlefield.get_grid(px, py).get_occupant())
# check whether the target is hit
if random.random() <= accuracy:
occupant.get_damage(damage)
return 'weapon hit ' + occupant.get_name() + '!'
return 'weapon missed!'
def shoot_projectile_weapon(self, x: int, y: int, weapon: weapons.ProjectileWeapon) -> list[str]:
"""
Fire a projectile weapon from (x, y) at a given direction and range. The weapon deals
certain damage to the target hit
:param x: the x-coordinate of starting point
:param y: the y-coordinate of the starting point
:param weapon: the weapon used
:return: the targets hit by the weapon
"""
targets = []
# generate sound and heat at starting position
self.battlefield.generate_heat(x, y, weapon.config.heat_emission)
self.battlefield.generate_heat(x, y, weapon.config.sound_emission)
# set target location
px, py = x, y
if weapon.direction == message.UP:
py -= weapon.range
elif weapon.direction == message.DOWN:
py += weapon.range
elif weapon.direction == message.LEFT:
px -= weapon.range
elif weapon.direction == message.RIGHT:
px += weapon.range
# examine the grids in the range
for i in range(max(0, px - weapon.config.impact_radius), min(len(self.battlefield.field[0]), px + weapon.config.impact_radius + 1)):
for j in range(max(0, py - weapon.config.impact_radius), min(len(self.battlefield.field), py + weapon.config.impact_radius + 1)):
if (i - px) ** 2 + (j - py) ** 2 <= weapon.config.impact_radius ** 2:
# deals damage to the target
occupant = self.battlefield.get_grid(i, j).get_occupant()
if isinstance(occupant, IDamageable):
# calculate damage decay
net_damage = weapon.config.damage.damage - weapon.config.impact_damage_decay * int(((i - px) ** 2 + (j - py) ** 2) ** 0.5)
occupant.get_damage(replace(weapon.config.damage, damage=net_damage))
targets.append("weapon hit " + occupant.get_name() + '!')
return targets