-
Notifications
You must be signed in to change notification settings - Fork 0
/
client.py
executable file
·148 lines (126 loc) · 5.29 KB
/
client.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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import socket, json
import random, pprint
import sys
import math
import re
class arith_list(list):
def __add__(self, other):
return arith_list([x + y for x, y in zip(self, other)])
def __rmul__(self, other):
return arith_list([x * other for x in self])
class Planet:
def __init__(self, json):
self.player_id = json['owner_id']
self.ships = arith_list(json['ships'])
self.production = arith_list(json['production'])
self.x = json['x']
self.y = json['y']
self.id = json['id']
self.incoming_fleets = []
def dist(self, other):
return int(math.ceil(math.sqrt((self.x-other.x)**2 + (self.y-other.y)**2)))
def add_incoming_fleet(self, fleet):
self.incoming_fleets += [fleet]
# Sends a fleet consisting of "ships" units from this planet to the planet "other".
def flyto(self, other, ships):
return ("send %s %s %d %d %d" % (self.id, other.id, ships[0], ships[1], ships[2]))
class Fleet:
def __init__(self, json, planets):
self.id = json['id']
self.player_id = json['owner_id']
target_string = json['target']
origin_string = json['origin']
self.target = [planet for planet in planets if planet.id == target_string][0]
self.origin = [planet for planet in planets if planet.id == origin_string][0]
self.ships = json['ships']
self.eta = json['eta']
def can_intercept(self, origin_planet, current_round):
combined_ships = origin_planet.ships
for i in range(0, len(self.target.ships)):
combined_ships[i] += self.target.ships[i]
return (origin_planet.ships[0] > 0 or origin_planet.ships[1] > 0 or origin_planet.ships[2] > 0 ) and origin_planet.dist(self.target) < (self.eta - current_round) and self.battle(self.ships, combined_ships)
def will_conquer_target(self):
return sum(self.battle(self.ships, self.target.ships)[1]) == 0
@staticmethod
def battle(s1,s2):
ships1 = s1[::]
ships2 = s2[::]
while sum(ships1) > 0 and sum(ships2) >0:
new1 = Fleet.battle_round(ships2,ships1)
ships2 = Fleet.battle_round(ships1,ships2)
ships1 = new1
#print ships1,ships2
ships1 = map(int,ships1)
ships2 = map(int,ships2)
#print ships1,ships2
return ships1, ships2
@staticmethod
def battle_round(attacker,defender):
#nur eine asymmetrische runde. das hier muss mal also zweimal aufrufen.
numships = len(attacker)
defender = defender[::]
for def_type in range(0,numships):
for att_type in range(0,numships):
multiplier = 0.1
absolute = 1
if (def_type-att_type)%numships == 1:
multiplier = 0.25
absolute = 2
if (def_type-att_type)%numships == numships-1:
multiplier = 0.01
defender[def_type] -= (attacker[att_type]*multiplier) + (attacker[att_type] > 0) * absolute
defender[def_type] = max(0,defender[def_type])
return defender
class State:
def __init__(self, json):
self.planets = [Planet(p) for p in json['planets']]
self.fleets = [Fleet(p, self.planets) for p in json['fleets']]
for f in self.fleets:
f.target.add_incoming_fleet(f)
self.player_id = json['player_id']
self.round = json['round']
def my(self, thing):
return thing.player_id == self.player_id
@property
def my_planets(self):
return [p for p in self.planets if self.my(p)]
@property
def neutral_planets(self):
return [p for p in self.planets if p.player_id == 0]
@property
def enemy_planets(self):
return [p for p in self.planets if p.player_id != 0 and not self.my(p)]
def play(user, password, ai):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('spacegoo.gpn.entropia.de', 6000))
io = s.makefile('rw')
def write(data):
io.write('%s\n' % (data,))
io.flush()
write('login %s %s' % (user, password))
while True:
data = io.readline().strip()
if not data:
return
if data[0] == "{":
state = json.loads(data)
if state['winner'] is not None:
break
s = State(state)
write(ai(s))
print("\r[{}/{}] {} - {} - {} ".format(state['round'], state['max_rounds'],
sum([sum(planet.ships) for planet in s.my_planets]) + sum([sum(fleet.ships) for fleet in s.fleets if
fleet.player_id == s.player_id]),
sum([sum(planet.ships) for planet in s.neutral_planets]),
sum([sum(planet.ships) for planet in s.enemy_planets]) + sum([sum(fleet.ships) for fleet in s.fleets if
not fleet.player_id == s.player_id])),
end='')
elif re.match('command received|welcome|calculating|waiting for', data):
pass
elif re.match('game ended', data):
print()
msg = data.replace('player 1', 'YOU' if s.player_id == 1 else 'enemy')
msg = msg.replace('player 2', 'YOU' if s.player_id == 2 else 'enemy')
print(msg)
else:
print(data)