-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathagent.py
More file actions
137 lines (108 loc) · 4.83 KB
/
Copy pathagent.py
File metadata and controls
137 lines (108 loc) · 4.83 KB
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
import os
import uuid
from flask import Flask, request, jsonify
from threading import Lock
from collections import deque
# --- Import your corrected game engine logic ---
# Make sure case_closed_game.py is in the same directory
from case_closed_game import Game, Direction, GameResult
# Flask API server setup
app = Flask(__name__)
# A lock is CRITICAL to prevent race conditions when multiple agents
# Global in-memory game state (single game object kept by agent server)
GLOBAL_GAME = Game()
LAST_POSTED_STATE = {}
# Lock to protect updates to GLOBAL_GAME and LAST_POSTED_STATE
game_lock = Lock()
# Basic identity (used by judge.check_latency)
PARTICIPANT = "ParticipantX"
AGENT_NAME = "AgentX"
@app.route("/", methods=["GET"])
def info():
"""Basic health/info endpoint used by the judge to check connectivity.
Returns participant and agent_name (so Judge.check_latency can create Agent objects).
"""
return jsonify({"participant": PARTICIPANT, "agent_name": AGENT_NAME}), 200
def _update_local_game_from_post(data: dict):
"""Update the local GLOBAL_GAME using the JSON posted by the judge.
The judge posts a dictionary with keys matching the Judge.send_state payload
(board, agent1_trail, agent2_trail, agent1_length, agent2_length, agent1_alive,
agent2_alive, agent1_boosts, agent2_boosts, turn_count).
"""
with game_lock:
# store raw for debugging
LAST_POSTED_STATE.clear()
LAST_POSTED_STATE.update(data)
# Update board grid if provided
if "board" in data:
try:
GLOBAL_GAME.board.grid = data["board"]
except Exception:
pass
# Update agents (trail positions and lengths)
if "agent1_trail" in data:
GLOBAL_GAME.agent1.trail = deque(tuple(p) for p in data["agent1_trail"])
if "agent2_trail" in data:
GLOBAL_GAME.agent2.trail = deque(tuple(p) for p in data["agent2_trail"])
if "agent1_length" in data:
GLOBAL_GAME.agent1.length = int(data["agent1_length"])
if "agent2_length" in data:
GLOBAL_GAME.agent2.length = int(data["agent2_length"])
if "agent1_alive" in data:
GLOBAL_GAME.agent1.alive = bool(data["agent1_alive"])
if "agent2_alive" in data:
GLOBAL_GAME.agent2.alive = bool(data["agent2_alive"])
if "agent1_boosts" in data:
GLOBAL_GAME.agent1.boosts_remaining = int(data["agent1_boosts"])
if "agent2_boosts" in data:
GLOBAL_GAME.agent2.boosts_remaining = int(data["agent2_boosts"])
if "turn_count" in data:
GLOBAL_GAME.turns = int(data["turn_count"])
@app.route("/send-state", methods=["POST"])
def receive_state():
"""Judge calls this to push the current game state to the agent server.
The agent should update its local representation and return 200.
"""
data = request.get_json()
if not data:
return jsonify({"error": "no json body"}), 400
_update_local_game_from_post(data)
return jsonify({"status": "state received"}), 200
@app.route("/send-move", methods=["GET"])
def send_move():
"""Judge calls this (GET) to request the agent's move for the current tick.
Query params the judge sends (optional): player_number, attempt_number,
random_moves_left, turn_count. Agents can use this to decide.
Return format: {"move": "DIRECTION"} or {"move": "DIRECTION:BOOST"}
where DIRECTION is UP, DOWN, LEFT, or RIGHT
and :BOOST is optional to use a speed boost (move twice)
"""
player_number = request.args.get("player_number", default=1, type=int)
# Access the latest state the judge posted
with game_lock:
state = dict(LAST_POSTED_STATE)
my_agent = GLOBAL_GAME.agent1 if player_number == 1 else GLOBAL_GAME.agent2
boosts_remaining = my_agent.boosts_remaining
# -----------------your code here-------------------
# Simple example: always go RIGHT (replace this with your logic)
# To use a boost: move = "RIGHT:BOOST"
move = "RIGHT"
# Example: Use boost if available and it's late in the game
# turn_count = state.get("turn_count", 0)
# if boosts_remaining > 0 and turn_count > 50:
# move = "RIGHT:BOOST"
# -----------------end code here--------------------
return jsonify({"move": move}), 200
@app.route("/end", methods=["POST"])
def end_game():
"""Judge notifies agent that the match finished and provides final state.
We update local state for record-keeping and return OK.
"""
data = request.get_json()
if data:
_update_local_game_from_post(data)
return jsonify({"status": "acknowledged"}), 200
if __name__ == "__main__":
# For development only. Port can be overridden with the PORT env var.
port = int(os.environ.get("PORT", "5008"))
app.run(host="0.0.0.0", port=port, debug=True)