Skip to content

Commit

Permalink
update hw kp race with both simulated server and strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
BriFuture committed Oct 16, 2019
1 parent 113abea commit 99d7029
Show file tree
Hide file tree
Showing 57 changed files with 4,505 additions and 0 deletions.
16 changes: 16 additions & 0 deletions 19-q3q4/huawei kunpen race/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
## 华为云鲲鹏开发者大赛

这是 2019 年参加 “华为云鲲鹏开发者大赛” 时编写的一些代码:

`brifuture` 文件夹里面是我编写的策略。只编写了一天,效果并不好,还有很多策略没有实现,打不过 AI,最好的成绩只有 300 多分。

`server` 文件夹里面是模拟官方的服务器,根据官方的文档说明编写的自定义的服务器,大部分功能都实现了,但仍有小部分的 bug 未解决。

**Note:解题策略和服务器仅供参考。**

-----
官方资源:

[赛题说明文档](https://bbs.huaweicloud.com/forum/thread-21027-1-1.html)

[试题工程](https://developer-res-cbc-cn.obs.cn-north-1.myhwclouds.com/competition/%E5%8D%8E%E4%B8%BA%E4%BA%91%E9%B2%B2%E9%B9%8F%E5%BC%80%E5%8F%91%E8%80%85%E5%A4%A7%E8%B5%9B-%E8%AF%95%E9%A2%98%E5%B7%A5%E7%A8%8B0801.zip)
1 change: 1 addition & 0 deletions 19-q3q4/huawei kunpen race/brifuture/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
brifuture.zip
Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
# encoding:utf8
'''
客户端对数据的接受和对已生成数据的发送,选手可以不关注此模块
'''

import socket
import json

from ballclient.service import service
import ballclient.service.constants as constants
import traceback
from ballclient.util import logger
from time import sleep

_socket = None

SOCKET_CACHE = 1024 * 20


def try_again(func):
def wraper(*args, **kwargs):
connect_time = 1
while connect_time <= 300:
try:
return func(*args, **kwargs)
except Exception:
if connect_time % 10 == 0:
logger.warning("connect server failed.....connect_time:%s" % connect_time)
connect_time += 1
sleep(0.2)
logger.fatal("can not connect with server. %s,%s" % args)
exit(1)
return wraper

@try_again
def connect_socket(ip=None, port=None):
global _socket
_socket.connect((ip, port))


def start(ip=None, port=None):
global _socket
_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
data = None
try:
connect_socket(ip,port)

logger.debug("Tri to register.")
register()
while 1:
data = _receive()
if data is None:
break
# logger.debug(data)

if data['msg_name'] == "round":
message = service.round(data)
send_dict(message)
elif data['msg_name'] == "leg_start":
service.leg_start(data)
elif data['msg_name'] == "leg_end":
service.leg_end(data)
elif data['msg_name'] == "game_over":
service.game_over(data)
logger.info("Server Exit")
return
else:
print("invalid msg_name.")
except socket.error:
print("can not connect with server. %s,%s" % (ip, port))
exit()
except Exception as e:
print("[start] some error happend: %s. the receive data: %s" % (e, data) )
traceback.print_exc()
finally:
if _socket:
_socket.close()
logger.info("Client Closed")


def register():
'''
register logic
:return:
'''
data = {"msg_name": "registration",
"msg_data": {"team_name": constants.team_name,
"team_id": constants.team_id}}
# print(f"[Register] {data}")
send_dict(data)


def send_dict(data):
data_str = json.dumps(data)
_socket.sendall(add_str_len(data_str).encode())


class Receiver(object):
def __init__(self):
self._cache = ""
self.remainBytes = 0

def __call__(self, *args, **kwargs):
while 1:
d = None
try:
d = _socket.recv(SOCKET_CACHE).decode()
# logger.debug(f"Data: {d}, {len(d)}")
if len(d) == 0:
return None
if self.remainBytes == 0:

if d[0:5].isdigit() and d[5] == "{":
need = int(d[0:5])
self.remainBytes = need - (len(d) - 5)
if(self.remainBytes == 0):
self._cache = ""
data = remove_json_num(d)
return json.loads(data)
else:
self._cache = d
else:
self.remainBytes -= len(d)
if self.remainBytes == 0:
data = remove_json_num(self._cache + d)
# logger.debug(self._cache + d)
self._cache = ""
return json.loads(data)
else:
self._cache += d
except ConnectionResetError:
print("can not connect with server.")
exit()
except Exception as e:
print("[Receiver] receive data error. cach the data and wait for next.", e)
traceback.print_exc()
break


_receive = Receiver()

def add_str_len(msg_data):
length = str(len(msg_data))
index = 5 - len(length)
if index < 0:
raise Exception("the return msg data is too long. the length > 99999.")
return '0' * index + length + msg_data


def remove_json_num(msg):
return msg[5:]


"""
# def _receive():
# d = _socket.recv(SOCKE_CACH)
# data = remove_json_num(d)
# return json.loads(data)
def receive_game_data():
try:
data = _receive()
if data['msg_name'] == "game_over":
service.exec_game_over()
return 0
else:
return_msg = service.exec_round(data)
send_msg = add_str_len(json.dumps(return_msg))
_socket.sendall(send_msg)
except:
print('error receive data......')
return 1
"""
30 changes: 30 additions & 0 deletions 19-q3q4/huawei kunpen race/brifuture/client/ballclient/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# encoding:utf8
'''
入口方法,选手不关注
'''


from ballclient import util
import sys

if __name__ == "__main__":
print(sys.argv)
if len(sys.argv) != 4:
print("The parameters has error. (TeamID server_ip server_port)")
exit()
team_id = sys.argv[1]
server_ip = sys.argv[2]
port = sys.argv[3]
print("start client....................")
if team_id.isdigit() and port.isdigit():
team_id = int(team_id)
port = int(port)
util.createShareLogger("brifuture_%s.log" % team_id, stream=True)
else:
print("team_id and port must be digit.")
exit()

import ballclient.service.constants as constants
from ballclient.comunicate import client
constants.team_id = team_id
client.start( server_ip, port)
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
from .gameteam import BasePlayer, BaseTeam, _ForceBeat, _ForceThink

class ClientPlayer(BasePlayer):
PrivilegeForce = _ForceBeat

def __init__(self, p):
BasePlayer.__init__(self, p["id"], p["team"])
self.x = p["x"]
self.y = p["y"]
self.score = p["score"]
self.visible = True
self.lastAction = None
self.nextPos = (self.x, self.y)
self.posStack = [] # 保留最近 n 次的位置
self.visualArea = [[0, 0], [0, 0]]

def distance(self, x, y):
return abs(self.x - x) + abs(self.y - y)

def isInvision(self, x, y):
if abs(self.x - x) <= ClientTeam.Vision and abs(self.y - y) <= ClientTeam.Vision:
return True
return False

def update(self, p):
self.lastX = self.x
self.lastY = self.y
BasePlayer.__init__(self, p["id"], p["team"])
self.x = p["x"]
self.y = p["y"]
self.score = p["score"]

def __repr__(self):
return '<Player [%s:%d (%d, %d)]> ' % (self.team, self.id, self.x, self.y)

class ClientTeam(BaseTeam):

Width = 20
Height = 20
Vision = 3

def __init__(self, id = 0):
BaseTeam.__init__(self)
self.meteor = None
self.tunnel = None
self.wormhole = None
self.id = id

# key 是 player 的 id, value 是 ClientPlayer 对象
self.players = {}
self.powers = [] # {'point': 1, 'x': 12, 'y': 2}
self.playerNum = 0
self.privilege = False

def addPlayer(self, playerInfo, replace=True):
player = ClientPlayer(playerInfo)
if not replace and player.id in self.players:
self.players[player.id].update(playerInfo)
else:
self.players[player.id] = player
self.playerNum = len(self.players)

def nearmate(self, x, y, dis = 5):
count = 0
for p in self.players.values():
if abs(p.x - x) <= dis and abs(p.y - y) <= dis:
count += 1
return count

def isMeteor(self, x, y):
"""Return True if meteor,
if x, y is out of boundary, return True
"""
for m in self.meteor:
if x == m["x"] and y == m["y"]:
return True

if x < 0 or x >= ClientTeam.Width or y < 0 or y >= ClientTeam.Height:
return True
return False

def isTunnel(self, x, y):
"""Return Tunnel Dict if found, else None
{"x": 3, "y": 1, "direction": "down"}
"""
for t in self.tunnel:
if t["x"] == x and t["y"] == y:
return t
return None

def isWormhole(self, x, y):
"""Return wormhole if found, else None
{"name": "a","x": 4, "y": 1}
"""
for wh in self.wormhole:
if wh["x"] == x and wh["y"] == y:
return wh
return None

def peerWormhole(self, wh):
"""Return Peer wormhole
"""
name = wh["name"]
if name.isupper():
exp = name.lower()
else:
exp = name.upper()

for h in self.wormhole:
if h["name"] == exp:
return h

def isPlayer(self, x, y, exceptPlayer=None):
for p in self.players.values():
if p == exceptPlayer:
continue
if p.x == x and p.y == y:
return p
if p.nextPos[0] == x and p.nextPos[1] == y:
return p
return None

def isPower(self, x, y):
"""Return Power point if found
"""
for p in self.powers:
if p["x"] == x and p["y"] == y:
return p["point"]
return None

def tunnelNext(self, tunnel):
"""direct 是 tunnel 的方向,
x y 是 tunnel 的位置
"""
direct = tunnel["direction"]
x = tunnel["x"]
y = tunnel["y"]
if direct == "right":
x += 1
elif direct == "left":
x -= 1
elif direct == "down":
y += 1
elif direct == "up":
y -= 1
# cascade tunnel
t = self.isTunnel(x, y)
if t is not None:
return self.tunnelNext(t)
return x, y

class ClientMap():
pass
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#global variable here
team_id = 1125

team_name = "qqcy" # decided by yourself.
Loading

0 comments on commit 99d7029

Please sign in to comment.