Skip to content

Commit 49405fd

Browse files
committed
0.1.6 - Manually Play
1 parent ca3922d commit 49405fd

File tree

5 files changed

+200
-79
lines changed

5 files changed

+200
-79
lines changed

kaggle_environments/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from .core import *
1818
from . import utils
1919

20-
version = "0.1.5"
20+
version = "0.1.6"
2121

2222
__all__ = ["environments", "evaluate", "make", "register", "utils", "version"]
2323

kaggle_environments/core.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,16 @@
1414

1515
import copy
1616
import json
17+
import uuid
1718
from .errors import DeadlineExceeded, FailedPrecondition, Internal, InvalidArgument
1819
from .utils import get, has, get_player, process_schema, schemas, structify, timeout
1920

2021
# Registered Environments.
2122
environments = {}
2223

24+
# Registered Interactive Sessions.
25+
interactives = {}
26+
2327

2428
def register(name, environment):
2529
"""
@@ -90,6 +94,7 @@ def __init__(
9094
html_renderer=None,
9195
debug=False,
9296
):
97+
self.id = str(uuid.uuid1())
9398
self.debug = debug
9499

95100
err, specification = self.__process_specification(specification)
@@ -263,6 +268,21 @@ def render(self, **kwargs):
263268
raise InvalidArgument(
264269
"Available render modes: human, ansi, html, ipython")
265270

271+
def play(self, agents=[], **kwargs):
272+
"""
273+
Renders a visual representation of the environment and allows interactive action selection.
274+
275+
Args:
276+
**kwargs (dict): Args directly passed into render(). Mode is fixed to ipython.
277+
278+
Returns:
279+
None: prints directly to an IPython notebook
280+
"""
281+
env = self.clone()
282+
trainer = env.train(agents)
283+
interactives[env.id] = (env, trainer)
284+
env.render(mode="ipython", interactive=True, **kwargs)
285+
266286
def train(self, agents=[]):
267287
"""
268288
Setup a lightweight training environment for a single agent.
@@ -344,6 +364,7 @@ def toJSON(self):
344364
spec = self.specification
345365
return copy.deepcopy(
346366
{
367+
"id": self.id,
347368
"name": spec.name,
348369
"title": spec.title,
349370
"description": spec.description,
@@ -365,6 +386,22 @@ def toJSON(self):
365386
}
366387
)
367388

389+
def clone(self):
390+
"""
391+
Returns:
392+
Environment: A copy of the current environment.
393+
"""
394+
return Environment(
395+
specification=self.specification,
396+
configuration=self.configuration,
397+
steps=self.steps,
398+
agents=self.agents,
399+
interpreter=self.interpreter,
400+
renderer=self.renderer,
401+
html_renderer=self.html_renderer,
402+
debug=self.debug,
403+
)
404+
368405
@property
369406
def __state_schema(self):
370407
if not hasattr(self, "__state_schema_value"):

kaggle_environments/envs/connectx/connectx.js

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,18 @@
1313
// limitations under the License.
1414

1515
function renderer({
16-
parent,
17-
step,
18-
frame,
16+
act,
1917
agents,
2018
environment,
21-
width = 400,
19+
frame,
2220
height = 400,
21+
interactive,
22+
isInteractive,
23+
parent,
24+
step,
2325
update,
26+
width = 400,
2427
}) {
25-
// Canvas Setup.
26-
let canvas = parent.querySelector("canvas");
27-
if (!canvas) {
28-
canvas = document.createElement("canvas");
29-
parent.appendChild(canvas);
30-
31-
canvas.addEventListener("click", () => {
32-
console.log("canvas click");
33-
});
34-
}
35-
3628
// Configuration.
3729
const { rows, columns, inarow } = environment.configuration;
3830

@@ -49,6 +41,23 @@ function renderer({
4941
const xOffset = Math.max(0, (width - cellSize * columns) / 2);
5042
const yOffset = Math.max(0, (height - cellSize * rows) / 2);
5143

44+
// Canvas Setup.
45+
let canvas = parent.querySelector("canvas");
46+
if (!canvas) {
47+
canvas = document.createElement("canvas");
48+
parent.appendChild(canvas);
49+
50+
if (interactive) {
51+
canvas.addEventListener("click", evt => {
52+
if (!isInteractive()) return;
53+
const rect = evt.target.getBoundingClientRect();
54+
const col = Math.floor((evt.clientX - rect.left - xOffset) / cellSize);
55+
if (col >= 0 && col < columns) act(col);
56+
});
57+
}
58+
}
59+
canvas.style.cursor = isInteractive() ? "pointer" : "default";
60+
5261
// Character Paths (based on 100x100 tiles).
5362
const kPath = new Path2D(
5463
`M78.3,96.5c-0.1,0.4-0.5,0.6-1.1,0.6H64.9c-0.7,0-1.4-0.3-1.9-1l-20.3-26L37,75.5v20.1 c0,0.9-0.5,1.4-1.4,1.4H26c-0.9,0-1.4-0.5-1.4-1.4V3.9c0-0.9,0.5-1.4,1.4-1.4h9.5C36.5,2.5,37,3,37,3.9v56.5l24.3-24.7 c0.6-0.6,1.3-1,1.9-1H76c0.6,0,0.9,0.2,1.1,0.7c0.2,0.6,0.1,1-0.1,1.2l-25.7,25L78,95.1C78.4,95.5,78.5,95.9,78.3,96.5z`

kaggle_environments/envs/tictactoe/tictactoe.js

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,32 +12,44 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
function renderer({
16-
agents,
17-
parent,
18-
step,
19-
frame,
20-
environment,
21-
width = 400,
22-
height = 400,
23-
update,
24-
}) {
15+
async function renderer(context) {
16+
const {
17+
act,
18+
agents,
19+
environment,
20+
frame,
21+
height = 400,
22+
interactive,
23+
isInteractive,
24+
parent,
25+
step,
26+
update,
27+
width = 400,
28+
} = context;
29+
30+
// Common Dimensions.
31+
const canvasSize = Math.min(height, width);
32+
const unit = 8;
33+
const offset = canvasSize > 400 ? canvasSize * 0.1 : unit / 2;
34+
const cellSize = (canvasSize - offset * 2) / 3;
35+
2536
// Canvas Setup.
2637
let canvas = parent.querySelector("canvas");
2738
if (!canvas) {
2839
canvas = document.createElement("canvas");
2940
parent.appendChild(canvas);
3041

31-
canvas.addEventListener("click", () => {
32-
console.log("canvas click");
33-
});
42+
if (interactive) {
43+
canvas.addEventListener("click", evt => {
44+
if (!isInteractive()) return;
45+
const rect = evt.target.getBoundingClientRect();
46+
const x = evt.clientX - rect.left - offset;
47+
const y = evt.clientY - rect.top - offset;
48+
act(Math.floor(x / cellSize) + Math.floor(y / cellSize) * 3);
49+
});
50+
}
3451
}
35-
36-
// Common Dimensions.
37-
const canvasSize = Math.min(height, width);
38-
const unit = 8;
39-
const offset = canvasSize > 400 ? canvasSize * 0.1 : unit / 2;
40-
const cellSize = (canvasSize - offset * 2) / 3;
52+
canvas.style.cursor = isInteractive() ? "pointer" : "default";
4153

4254
// Canvas setup and reset.
4355
let c = canvas.getContext("2d");

0 commit comments

Comments
 (0)