Skip to content

Commit 5b6e049

Browse files
committed
Allow LANGUAGE file to override displayed language
If a LANGUAGE file is included in the bot zip file, the first line of it will be used to override the displayed language used. It has no impact on how the bot is compiled or run. Closes #265
1 parent e525281 commit 5b6e049

File tree

7 files changed

+230
-0
lines changed

7 files changed

+230
-0
lines changed

tests/worker/languageBot/LANGUAGE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
TestLanguage

tests/worker/languageBot/MyBot.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from hlt import *
2+
from networking import *
3+
4+
myID, gameMap = getInit()
5+
sendInit("PythonBot")
6+
7+
while True:
8+
moves = []
9+
gameMap = getFrame()
10+
for y in range(gameMap.height):
11+
for x in range(gameMap.width):
12+
if gameMap.getSite(Location(x, y)).owner == myID:
13+
moves.append(Move(Location(x, y), int(random.random() * 5)))
14+
sendFrame(moves)

tests/worker/languageBot/hlt.py

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import random
2+
import math
3+
import copy
4+
5+
STILL = 0
6+
NORTH = 1
7+
EAST = 2
8+
SOUTH = 3
9+
WEST = 4
10+
11+
DIRECTIONS = [a for a in range(0, 5)]
12+
CARDINALS = [a for a in range(1, 5)]
13+
14+
ATTACK = 0
15+
STOP_ATTACK = 1
16+
17+
class Location:
18+
def __init__(self, x=0, y=0):
19+
self.x = x
20+
self.y = y
21+
class Site:
22+
def __init__(self, owner=0, strength=0, production=0):
23+
self.owner = owner
24+
self.strength = strength
25+
self.production = production
26+
class Move:
27+
def __init__(self, loc=0, direction=0):
28+
self.loc = loc
29+
self.direction = direction
30+
31+
class GameMap:
32+
def __init__(self, width = 0, height = 0, numberOfPlayers = 0):
33+
self.width = width
34+
self.height = height
35+
self.contents = []
36+
37+
for y in range(0, self.height):
38+
row = []
39+
for x in range(0, self.width):
40+
row.append(Site(0, 0, 0))
41+
self.contents.append(row)
42+
43+
def inBounds(self, l):
44+
return l.x >= 0 and l.x < self.width and l.y >= 0 and l.y < self.height
45+
46+
def getDistance(self, l1, l2):
47+
dx = math.abs(l1.x - l2.x)
48+
dy = math.abs(l1.y - l2.y)
49+
if dx > self.width / 2:
50+
dx = self.width - dx
51+
if dy > self.height / 2:
52+
dy = self.height - dy
53+
return dx + dy
54+
55+
def getAngle(self, l1, l2):
56+
dx = l2.x - l1.x
57+
dy = l2.y - l1.y
58+
59+
if dx > self.width - dx:
60+
dx -= self.width
61+
elif -dx > self.width + dx:
62+
dx += self.width
63+
64+
if dy > self.height - dy:
65+
dy -= self.height
66+
elif -dy > self.height + dy:
67+
dy += self.height
68+
return math.atan2(dy, dx)
69+
70+
def getLocation(self, loc, direction):
71+
l = copy.deepcopy(loc)
72+
if direction != STILL:
73+
if direction == NORTH:
74+
if l.y == 0:
75+
l.y = self.height - 1
76+
else:
77+
l.y -= 1
78+
elif direction == EAST:
79+
if l.x == self.width - 1:
80+
l.x = 0
81+
else:
82+
l.x += 1
83+
elif direction == SOUTH:
84+
if l.y == self.height - 1:
85+
l.y = 0
86+
else:
87+
l.y += 1
88+
elif direction == WEST:
89+
if l.x == 0:
90+
l.x = self.width - 1
91+
else:
92+
l.x -= 1
93+
return l
94+
def getSite(self, l, direction = STILL):
95+
l = self.getLocation(l, direction)
96+
return self.contents[l.y][l.x]
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
from hlt import *
2+
import socket
3+
import traceback
4+
import struct
5+
from ctypes import *
6+
import sys
7+
8+
_productions = []
9+
_width = -1
10+
_height = -1
11+
12+
def serializeMoveSet(moves):
13+
returnString = ""
14+
for move in moves:
15+
returnString += str(move.loc.x) + " " + str(move.loc.y) + " " + str(move.direction) + " "
16+
return returnString
17+
18+
def deserializeMapSize(inputString):
19+
splitString = inputString.split(" ")
20+
21+
global _width, _height
22+
_width = int(splitString.pop(0))
23+
_height = int(splitString.pop(0))
24+
25+
def deserializeProductions(inputString):
26+
splitString = inputString.split(" ")
27+
28+
for a in range(0, _height):
29+
row = []
30+
for b in range(0, _width):
31+
row.append(int(splitString.pop(0)))
32+
_productions.append(row)
33+
34+
def deserializeMap(inputString):
35+
splitString = inputString.split(" ")
36+
37+
m = GameMap(_width, _height)
38+
39+
y = 0
40+
x = 0
41+
counter = 0
42+
owner = 0
43+
while y != m.height:
44+
counter = int(splitString.pop(0))
45+
owner = int(splitString.pop(0))
46+
for a in range(0, counter):
47+
m.contents[y][x].owner = owner
48+
x += 1
49+
if x == m.width:
50+
x = 0
51+
y += 1
52+
53+
for a in range(0, _height):
54+
for b in range(0, _width):
55+
m.contents[a][b].strength = int(splitString.pop(0))
56+
m.contents[a][b].production = _productions[a][b]
57+
58+
return m
59+
60+
def sendString(toBeSent):
61+
toBeSent += '\n'
62+
63+
sys.stdout.write(toBeSent)
64+
sys.stdout.flush()
65+
66+
def getString():
67+
return sys.stdin.readline().rstrip('\n')
68+
69+
def getInit():
70+
playerTag = int(getString())
71+
deserializeMapSize(getString())
72+
deserializeProductions(getString())
73+
m = deserializeMap(getString())
74+
75+
return (playerTag, m)
76+
77+
def sendInit(name):
78+
sendString(name)
79+
80+
def getFrame():
81+
return deserializeMap(getString())
82+
83+
def sendFrame(moves):
84+
sendString(serializeMoveSet(moves))

tests/worker/languageBot/run.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
python3 MyBot.py

tests/worker/testWorker.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,20 @@ def testStarterPackages(self):
4343
assert language == expectedLanguage
4444
assert errors == None
4545

46+
def testLanguageOverride(self):
47+
'''Use a LANGUAGE file to override the detected language'''
48+
LANGUAGE_BOT_PATH = "languageBot"
49+
50+
bot_dir = os.path.join(OUR_PATH, LANGUAGE_BOT_PATH)
51+
expectedLanguage = "TestLanguage"
52+
53+
language, errors = compiler.compile_anything(bot_dir)
54+
if errors is not None: print("Errors: " + "\n".join(errors))
55+
print("Language: " + language)
56+
57+
assert language == expectedLanguage
58+
assert errors == None
59+
4660
class GameTests(unittest.TestCase):
4761
def testNormalGame(self):
4862
'''Test the parsing of the output of runGame.sh'''

worker/compiler.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
MEMORY_LIMIT = 1500
2323

2424
BOT = "MyBot"
25+
LANGUAGE_FILE = "LANGUAGE"
2526
SAFEPATH = re.compile('[a-zA-Z0-9_.$-]+$')
2627

2728
class CD(object):
@@ -477,6 +478,20 @@ def detect_language(bot_dir):
477478
else:
478479
return detected_langs[0], None
479480

481+
def detect_language_file(bot_dir):
482+
with CD(bot_dir):
483+
try:
484+
with open(LANGUAGE_FILE, 'r') as lang_file:
485+
print("detected %s file" % LANGUAGE_FILE)
486+
language_name = lang_file.readline().strip()
487+
488+
if not language_name:
489+
return None
490+
else:
491+
return language_name
492+
except IOError:
493+
return None
494+
480495
def get_run_cmd(submission_dir):
481496
with CD(submission_dir):
482497
if os.path.exists('run.sh'):
@@ -518,6 +533,11 @@ def compile_anything(bot_dir, installTimeLimit=600, timelimit=600, max_error_len
518533
except Exception as e:
519534
print("error")
520535
print(e.strerror)
536+
537+
# allow LANGUAGE file to override language name
538+
override_name = detect_language_file(bot_dir)
539+
if override_name:
540+
name = override_name
521541
return name, None
522542
else:
523543
# limit length of reported errors

0 commit comments

Comments
 (0)