Skip to content

Commit 0e6ad97

Browse files
committed
Add logs
1 parent 169a4be commit 0e6ad97

4 files changed

Lines changed: 497 additions & 0 deletions

File tree

logs/robotrumble_sample/flail.js

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
const DB=false;
2+
3+
function robot(state, unit) {
4+
//console.log("Hello World!");
5+
6+
function getObj(x,y){
7+
return state.objByCoords(new Coords(x,y));
8+
}
9+
10+
//console.log(getObj(1,3));
11+
12+
function run(dir){
13+
if(DB){debug.log("trying",dir);}
14+
let D=dir;
15+
if(DB){debug.log("has",getObj(unit.coords.x+D.toCoords.y,unit.coords.y+D.toCoords.y));}
16+
if(!getObj(unit.coords.x+D.toCoords.x,unit.coords.y+D.toCoords.y)){
17+
if(DB){debug.log(""+D,getObj(unit.coords.x+D.toCoords.x,unit.coords.y+D.toCoords.y));}
18+
return Action.move(dir);
19+
}
20+
D=dir.rotateCw;
21+
if(!getObj(unit.coords.x+D.toCoords.x,unit.coords.y+D.toCoords.y)){
22+
if(DB){debug.log(""+D,getObj(unit.coords.x+D.toCoords.x,unit.coords.y+D.toCoords.y));}
23+
return Action.move(D);
24+
}
25+
D=dir.rotateCcw;
26+
if(!getObj(unit.coords.x+D.toCoords.x,unit.coords.y+D.toCoords.y)){
27+
if(DB){debug.log(""+D,getObj(unit.coords.x+D.toCoords.x,unit.coords.y+D.toCoords.y));}
28+
return Action.move(D);
29+
}
30+
return Action.move(dir);
31+
}
32+
33+
function flee(dir){
34+
if(DB){debug.log("trying",dir);}
35+
let D=dir;
36+
if(DB){debug.log("has",getObj(unit.coords.x+D.toCoords.y,unit.coords.y+D.toCoords.x));}
37+
if(!getObj(unit.coords.x+D.toCoords.x,unit.coords.y+D.toCoords.y)){
38+
if(DB){debug.log(""+D,getObj(unit.coords.x+D.toCoords.x,unit.coords.y+D.toCoords.y));}
39+
return Action.move(dir);
40+
}
41+
D=dir.rotateCw;
42+
if(!getObj(unit.coords.x+D.toCoords.x,unit.coords.y+D.toCoords.y)){
43+
if(DB){debug.log(""+D,getObj(unit.coords.x+D.toCoords.x,unit.coords.y+D.toCoords.y));}
44+
return Action.move(D);
45+
}
46+
D=dir.rotateCcw;
47+
if(!getObj(unit.coords.x+D.toCoords.x,unit.coords.y+D.toCoords.y)){
48+
if(DB){debug.log(""+D,getObj(unit.coords.x+D.toCoords.x,unit.coords.y+D.toCoords.y));}
49+
return Action.move(D);
50+
}
51+
return Action.attack(dir.opposite);
52+
}
53+
54+
let enemies = state.objsByTeam(state.otherTeam)
55+
if(enemies){
56+
let closestEnemy = _.minBy(enemies,
57+
e => e.coords.distanceTo(unit.coords) + e.health/10
58+
)
59+
let direction = unit.coords.directionTo(closestEnemy.coords);
60+
61+
if(unit.health<2){
62+
if(DB){debug.log("tas","flee");}
63+
if(closestEnemy.health<unit.health){
64+
return Action.attack(direction);
65+
}
66+
return flee(direction.opposite);
67+
}
68+
69+
if(unit.coords.distanceTo(closestEnemy.coords) < 3) {
70+
let closeGuys=0;
71+
for(let i=-2;i<3;i++){
72+
for(let j=-2;j<3;j++){
73+
let obj=getObj(closestEnemy.coords.x+i,closestEnemy.coords.y+j);
74+
if(obj&&obj.team==unit.team){
75+
closeGuys++;
76+
}
77+
}
78+
}
79+
if(closeGuys<2){
80+
if(DB){debug.log("tas","flee");}
81+
return run(direction.opposite);
82+
}
83+
if(unit.coords.distanceTo(closestEnemy.coords) === 1) {
84+
return Action.attack(direction);
85+
} else {
86+
if(DB){debug.log("task","attack");}
87+
return run(direction);
88+
}
89+
}
90+
let friends = state.objsByTeam(state.ourTeam);
91+
92+
let closestFriend = _.minBy(friends,
93+
f =>{
94+
let nearbyEnemey=false;
95+
96+
let enemies = state.objsByTeam(state.otherTeam)
97+
let closestEnemy = _.minBy(enemies,
98+
e => e.coords.distanceTo(f.coords) + e.health/10
99+
)
100+
if(f.coords.distanceTo(closestEnemy.coords)>2){
101+
return Infinity;
102+
}
103+
return f.coords.distanceTo(unit.coords);
104+
}
105+
)
106+
107+
if(closestFriend){
108+
let enemies = state.objsByTeam(state.otherTeam)
109+
let closestEnemy = _.minBy(enemies,
110+
e => e.coords.distanceTo(closestFriend.coords) + e.health/10
111+
)
112+
113+
if(closestFriend.coords.distanceTo(closestEnemy.coords)<3){
114+
if(DB){debug.log("task","friend");}
115+
return run(unit.coords.directionTo(closestEnemy.coords));
116+
}
117+
}
118+
}
119+
120+
let to = unit.coords.directionTo(new Coords(10,10));
121+
let inward = getObj(unit.coords.x+to.toCoords.x,unit.coords.y+to.toCoords.y);
122+
123+
if(!getObj(unit.coords.x+to.opposite.toCoords.x,unit.coords.y+to.opposite.toCoords.y)){
124+
if(DB){debug.log("task","out");}
125+
return run(unit.coords.directionTo(new Coords(10,10)).opposite);
126+
}
127+
128+
if(!inward){
129+
return Action.attack(to);
130+
}
131+
if(DB){debug.log("task","do nothing");}
132+
return null;
133+
}
134+
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
#
2+
# Unsupported browser type!
3+
# The Garage officially supports Chrome 85+, Microsoft Edge 85+, Firefox 78+, Opera 71+
4+
# The Garage DOES NOT support Safari
5+
# Your browser is: Safari 16.3
6+
#
7+
# If you cannot switch to a different browser, consider downloading Rumblebot, our command line tool
8+
# https://rr-docs.readthedocs.io/en/latest/rumblebot.html
9+
#
10+
11+
12+
from rumblelib import *
13+
from typing import (
14+
Dict,
15+
NamedTuple,
16+
Sequence,
17+
Hashable,
18+
List,
19+
Optional,
20+
Tuple,
21+
Set,
22+
)
23+
from collections import namedtuple
24+
import random
25+
26+
############################################################
27+
### To implement new strategies rewrite make_obj_plan()! ###
28+
############################################################
29+
30+
31+
robot_actions: Dict[
32+
str, Action
33+
] = {} # Global variable to store all actions in init_turn() and to be used in robot()
34+
35+
36+
shift_to_direction: Dict[Tuple, Direction] = {
37+
(1, 0): Direction.East,
38+
(-1, 0): Direction.West,
39+
(0, 1): Direction.South,
40+
(0, -1): Direction.North,
41+
}
42+
43+
44+
# A plan contains an .action for an .id
45+
# Plans are selected by *lowest* .score such that for each .target there is only one selection
46+
Plan = namedtuple(
47+
"Plan",
48+
[
49+
"id", # str: id of object
50+
"target", # Hashable: only one target will be selected from all equal targets
51+
"score", # float: minimum score is highest priority
52+
"action", # Action: action to be executed])
53+
],
54+
)
55+
56+
57+
def make_info(state: State) -> Dict:
58+
"""
59+
Return anything you want to pre-calculate at the beginning of a turn
60+
"""
61+
return {}
62+
63+
64+
def make_obj_plan(state: State, info: Dict, obj: Obj) -> Sequence[Plan]:
65+
"""
66+
Should emit a list of plans for the current object
67+
"""
68+
result: List[Plan] = []
69+
70+
enemies = state.objs_by_team(state.other_team)
71+
72+
if not enemies:
73+
return []
74+
75+
closest_enemies, distance = find_closest(obj, enemies, get_dist)
76+
closest_enemy = random.choice(closest_enemies)
77+
78+
shifts = get_directions_to(closest_enemy.coords - obj.coords)
79+
80+
for shift in shifts:
81+
assert shift != (0, 0) # should never happen
82+
83+
next_pos = obj.coords + Coords(shift.x, shift.y)
84+
85+
if is_spawn_turn(state.turn + 1) and not is_inside_nonspawn(next_pos):
86+
continue
87+
88+
direction = shift_to_direction[shift]
89+
90+
next_obj = state.obj_by_coords(next_pos)
91+
92+
if next_obj is not None and next_obj.team == state.other_team:
93+
action = Action.attack(direction)
94+
else:
95+
action = Action.move(direction)
96+
97+
plan = Plan(
98+
id=obj.id,
99+
target=next_pos,
100+
score=distance,
101+
action=action,
102+
)
103+
result.append(plan)
104+
105+
return result
106+
107+
108+
##############################################################
109+
### Following functions probably do not have to be changed ###
110+
##############################################################
111+
112+
Shift = namedtuple("Shift", "x y")
113+
114+
115+
def init_turn(state: State):
116+
"""
117+
run once for each turn
118+
use this to initialize global variables to be used by all units
119+
"""
120+
global robot_actions
121+
122+
try:
123+
info = make_info(state)
124+
plans = make_plans(state, info)
125+
selected_actions = select_plans(plans)
126+
robot_actions = selected_actions
127+
except Exception as exc:
128+
import traceback
129+
130+
traceback.print_exc()
131+
132+
133+
def robot(state: State, unit: Obj) -> Optional[Action]:
134+
"""
135+
called for each bot and needs to return an action
136+
"""
137+
138+
return robot_actions.get(unit.id) # bots without plans will return None and be idle
139+
140+
141+
def make_plans(state: State, info: Dict) -> List[Plan]:
142+
plans: List[Plan] = []
143+
144+
for obj in state.objs_by_team(state.our_team):
145+
plans.extend(make_obj_plan(state, info, obj))
146+
147+
return plans
148+
149+
150+
def select_plans(plans: List[Plan]) -> Dict[str, Action]:
151+
# Simple greedy selection by lowest score
152+
targets_used: Set[Hashable] = set()
153+
random.shuffle(plans) # to avoid systematic priority effects
154+
plans = sorted(plans, key=lambda x: x.score)
155+
156+
result: Dict[str, Action] = {}
157+
158+
for plan in plans:
159+
if plan.id in result or (
160+
plan.target is not None and plan.target in targets_used
161+
):
162+
continue
163+
164+
result[plan.id] = plan.action
165+
targets_used.add(plan.target)
166+
167+
return result
168+
169+
170+
def dist_from_center(coord: Coords):
171+
# "octagonal distance"
172+
dx = coord.x - 9
173+
dy = coord.y - 9
174+
return max(abs(dx), abs(dy), abs(dx) + abs(dy) - 4)
175+
176+
177+
def is_spawn_turn(turn: int) -> bool:
178+
return turn % 10 == 0
179+
180+
181+
def is_inside_field(coord: Coords):
182+
return dist_from_center(coord) <= 8
183+
184+
185+
def is_inside_nonspawn(coord: Coords):
186+
return dist_from_center(coord) < 8
187+
188+
189+
def is_spawn_region(coord: Coords):
190+
return dist_from_center(coord) == 8
191+
192+
193+
def get_dist(obj1: Obj, obj2: Obj) -> int:
194+
return obj1.coords.walking_distance_to(obj2.coords)
195+
196+
197+
def find_closest_idx(obj, others, dist_func) -> Tuple[List[int], Optional[int]]:
198+
"""
199+
Return indices of position from poses2 which is closest to pos1
200+
Also return distance
201+
"""
202+
if not others:
203+
return [], None
204+
205+
distances = [dist_func(obj, other) for other in others]
206+
207+
shortest_distance = min(distances)
208+
209+
indices = [
210+
i for i, distance in enumerate(distances) if distance == shortest_distance
211+
]
212+
213+
return (
214+
indices,
215+
shortest_distance,
216+
)
217+
218+
219+
def find_closest(obj, others, dist_func):
220+
closest_indices, distance = find_closest_idx(obj, others, get_dist)
221+
return [others[i] for i in closest_indices], distance
222+
223+
224+
def get_directions_to(shift: Shift) -> Set[Shift]:
225+
"""
226+
Returns all directions that would bring you closer along shift
227+
"""
228+
if shift == (0, 0):
229+
return {Shift(0, 0)}
230+
231+
result: Set[Shift] = set()
232+
233+
if shift.x > 0:
234+
result.add(Shift(1, 0))
235+
236+
if shift.x < 0:
237+
result.add(Shift(-1, 0))
238+
239+
if shift.y > 0:
240+
result.add(Shift(0, 1))
241+
242+
if shift.y < 0:
243+
result.add(Shift(0, -1))
244+
245+
return result
246+

0 commit comments

Comments
 (0)