Initial commit from Openverse UI
This commit is contained in:
209
README.md
Normal file
209
README.md
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
# TURN-BASED GAME DESIGN DOCUMENT
|
||||||
|
*(Environment Name: “Stellar Orchard”)*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Concept Paragraph
|
||||||
|
|
||||||
|
**Stellar Orchard** is a deterministic, turn-based strategy game where two rival horticulturists compete to cultivate the most thriving orchard on a distant exoplanet. The environment simulates a grid of orchard plots, each plot able to host an alien tree that produces **lumen fruit**—a glowing bioengineered product that yields energy points. Players must choose each turn to **Plant**, **Nurture**, or **Harvest** specific plots to maximize their total energy yield before the season ends. Weather and soil conditions are fixed by a deterministic seed at reset, ensuring reproducibility. The design, theme, and terminology are **completely unrelated to any negotiation or trading example**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Roles and Win Condition
|
||||||
|
|
||||||
|
- **Player Roles:**
|
||||||
|
- *Player A (Solar Gardener)*
|
||||||
|
- *Player B (Lunar Gardener)*
|
||||||
|
Each controls their own half of the orchard (plots tagged `A1–A5` for A; `B1–B5` for B).
|
||||||
|
|
||||||
|
- **Objective:**
|
||||||
|
Accumulate the highest **Energy Points (EP)** via strategic planting, nurturing, and harvesting of trees.
|
||||||
|
|
||||||
|
- **Win Conditions:**
|
||||||
|
- The game ends after **10 turns** or when both players have harvested all trees.
|
||||||
|
- The player with the **highest cumulative EP** wins.
|
||||||
|
- If total EPs are equal, the result is a **draw**.
|
||||||
|
- If a player performs two invalid moves consecutively, they **forfeit** the match and lose automatically.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Turn Structure and Determinism
|
||||||
|
|
||||||
|
- Fixed alternating turns: Player A → Player B → Player A → ...
|
||||||
|
- Each turn, a player chooses **one valid action**.
|
||||||
|
- Game ends after **Turn 10** (each player acts 5 times).
|
||||||
|
- A `random_seed` parameter initializes soil fertility levels and initial weather pattern with reproducible deterministic effects.
|
||||||
|
- No hidden randomness during play; outcomes are computed deterministically based on seed and previous actions.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Action Grammar (Machine-Parseable)
|
||||||
|
|
||||||
|
All player actions are deterministic commands describing their move this turn. Actions must match **exactly one** of the grammar patterns below.
|
||||||
|
|
||||||
|
| Action Type | Format | Description and Rule | Example (Valid) | Example (Invalid) and Reason |
|
||||||
|
|--------------|---------|---------------------|-----------------|------------------------------|
|
||||||
|
| **Plant** | `Plant:<plot>` | Plants a new tree on the specified empty plot. `<plot>` ∈ {A1–A5 (for Player A), B1–B5 (for Player B)} | `Plant:A3` | `Plant:C2` → Invalid (nonexistent plot) |
|
||||||
|
| **Nurture** | `Nurture:<plot>` | Boosts growth stage of one existing, unharvested tree on a valid occupied plot. | `Nurture:B4` | `Nurture:B6` → Invalid (out of range) |
|
||||||
|
| **Harvest** | `Harvest:<plot>` | Harvests a fully grown tree from the specified plot, removing it and collecting EP. | `Harvest:A1` | `Harvest:A1,A2` → Invalid (multiple plots not allowed) |
|
||||||
|
| **Pass** | `Pass` | Player skips the turn intentionally (strategic or necessary if no valid move). | `Pass` | `[Pass]` → Invalid (extra brackets not part of syntax) |
|
||||||
|
|
||||||
|
**Regular Expression Patterns**
|
||||||
|
- `^Plant:(A[1-5]|B[1-5])$`
|
||||||
|
- `^Nurture:(A[1-5]|B[1-5])$`
|
||||||
|
- `^Harvest:(A[1-5]|B[1-5])$`
|
||||||
|
- `^Pass$`
|
||||||
|
|
||||||
|
All valid actions will be wrapped by players inside `\boxed{{}}` at runtime, e.g., `\boxed{{Harvest:A1}}`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Game State Schema
|
||||||
|
|
||||||
|
Example `game_state` format:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"turn_number": 3,
|
||||||
|
"max_turns": 10,
|
||||||
|
"active_player": "Solar Gardener",
|
||||||
|
"plots": {
|
||||||
|
"A1": {"owner": "A", "status": "grown", "growth_level": 3},
|
||||||
|
"A2": {"owner": "A", "status": "empty", "growth_level": 0},
|
||||||
|
"A3": {"owner": "A", "status": "seedling", "growth_level": 1},
|
||||||
|
"B1": {"owner": "B", "status": "grown", "growth_level": 3},
|
||||||
|
"B2": {"owner": "B", "status": "harvested", "growth_level": 0}
|
||||||
|
},
|
||||||
|
"energy_points": {
|
||||||
|
"A": 15,
|
||||||
|
"B": 12
|
||||||
|
},
|
||||||
|
"soil_fertility": {
|
||||||
|
"A1": 0.9,
|
||||||
|
"A2": 0.6,
|
||||||
|
"B1": 0.8
|
||||||
|
},
|
||||||
|
"weather_pattern": "Radiant Skies",
|
||||||
|
"transcript": [
|
||||||
|
{"player": "A", "action": "Plant:A3"},
|
||||||
|
{"player": "B", "action": "Nurture:B1"}
|
||||||
|
],
|
||||||
|
"winner": null,
|
||||||
|
"random_seed": 57
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Initialization Rules
|
||||||
|
|
||||||
|
- `random_seed` is set during environment reset; it governs deterministic generation of:
|
||||||
|
- `soil_fertility` for each plot (each between 0.5 and 1.0).
|
||||||
|
- `weather_pattern` (chosen deterministically from a fixed set: Radiant Skies / Lunar Mist / Crystal Winds).
|
||||||
|
- `energy_points[A]` and `[B]` start at **0**.
|
||||||
|
- All plots start as `"empty"`.
|
||||||
|
- Observations include the common introduction, initial weather, soil fertility summary, and allowed actions.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Validation and Error Handling
|
||||||
|
|
||||||
|
On every step:
|
||||||
|
|
||||||
|
1. Extract literal content from `\boxed{{...}}` using `_extract_answer_content`.
|
||||||
|
2. Validate syntax against regex patterns.
|
||||||
|
3. Check logical validity:
|
||||||
|
- **Plant** → must target empty plot owned by that player.
|
||||||
|
- **Nurture** → must target already planted, not yet grown tree.
|
||||||
|
- **Harvest** → must target grown, unharvested tree.
|
||||||
|
- **Pass** → always valid.
|
||||||
|
4. Any violation triggers `set_invalid_move(player, reason)`, e.g.:
|
||||||
|
- `"Invalid format"`
|
||||||
|
- `"Plot not owned by player"`
|
||||||
|
- `"Plot already occupied"`
|
||||||
|
- `"Tree not ready to harvest"`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Terminal Conditions and Scoring
|
||||||
|
|
||||||
|
- **Automatic End:**
|
||||||
|
- When `turn_number >= max_turns`
|
||||||
|
- OR when all plots are `harvested` or `empty` (no active trees remain)
|
||||||
|
|
||||||
|
- **Scoring:**
|
||||||
|
- For each harvested tree: `EP += int(10 * soil_fertility[plot])`.
|
||||||
|
- No fractional points.
|
||||||
|
- Final score is the total `EP` accumulated.
|
||||||
|
|
||||||
|
- **Result Determination:**
|
||||||
|
- Higher total → **Winner**.
|
||||||
|
- Equal totals → **Draw**.
|
||||||
|
- Consecutive double invalid move by a player → automatic **Loss**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Player Prompt Specification
|
||||||
|
|
||||||
|
**Identity Context:**
|
||||||
|
“You are a cosmic horticulturist tending bioluminescent trees on the exoplanet Selora. Your goal is to maximize your orchard’s energy yield before the season ends.”
|
||||||
|
|
||||||
|
**Prompt Structure Includes:**
|
||||||
|
- Current turn number and remaining turns.
|
||||||
|
- Your current EP and plots' status summary.
|
||||||
|
- Weather pattern and soil fertility hints.
|
||||||
|
- List of all valid actions:
|
||||||
|
- `Plant:<plot>`
|
||||||
|
- `Nurture:<plot>`
|
||||||
|
- `Harvest:<plot>`
|
||||||
|
- `Pass`
|
||||||
|
- Explicit response requirement: “Put your final answer within `\boxed{{}}` at the end of your response.”
|
||||||
|
|
||||||
|
**Few-shot Examples:**
|
||||||
|
```
|
||||||
|
Example valid response:
|
||||||
|
I will start by planting my first tree in plot A2.
|
||||||
|
\boxed{{Plant:A2}}
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
Example invalid response:
|
||||||
|
Let's see how this goes!
|
||||||
|
\boxed{{Grow:A2}} # Invalid because 'Grow' is not a recognized action type.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Dialogue Elements:** None (pure command game). All player utterances (including justification text) get appended to transcript for transparency.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. API Mapping Plan
|
||||||
|
|
||||||
|
- **`reset(seed: Optional[int])`**
|
||||||
|
- Initializes `game_state` using the deterministic seed.
|
||||||
|
- Builds initial soil fertility and weather data.
|
||||||
|
- Clears all plots, transcript, and EPs.
|
||||||
|
- Returns the observation containing theme introduction and available actions.
|
||||||
|
|
||||||
|
- **`step(action: str)`**
|
||||||
|
- Extracts action content via `_extract_answer_content`.
|
||||||
|
- Validates syntax + legality.
|
||||||
|
- Updates game state deterministically (adjust plot status, growth level, EPs).
|
||||||
|
- Adds the player’s message and resulting action to transcript.
|
||||||
|
- Advances to the next turn or marks the game as terminal if conditions met.
|
||||||
|
- Returns updated observation, reward, and termination flag.
|
||||||
|
|
||||||
|
- **`_generate_player_prompt(player_id)`**
|
||||||
|
- Constructs text prompt including:
|
||||||
|
- Game identity summary
|
||||||
|
- Current turn, soil info, plot statuses
|
||||||
|
- Weather condition and EP scores
|
||||||
|
- List of valid actions and formatting requirement
|
||||||
|
- Few-shot examples above
|
||||||
|
- Returns formatted prompt string.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. Copy-Check Against the Example
|
||||||
|
|
||||||
|
All terms—**plots**, **trees**, **lumen fruit**, **Energy Points**, **soil fertility**, **weather pattern**, **Solar/Lunar Gardeners**, and **orchard management theme**—are *original* and entirely **unrelated to any negotiation, trading, or economic dialogue example**.
|
||||||
|
The `game_state` keys (`plots`, `soil_fertility`, `energy_points`, etc.) and all action types are unique to **Stellar Orchard** and do not replicate any element from other sample environments.
|
||||||
242
env.py
Normal file
242
env.py
Normal file
@@ -0,0 +1,242 @@
|
|||||||
|
```python
|
||||||
|
import re
|
||||||
|
import random
|
||||||
|
from typing import Any, Dict, Optional, Tuple, List
|
||||||
|
|
||||||
|
import textarena as ta
|
||||||
|
|
||||||
|
|
||||||
|
class StellarOrchardEnv(ta.Env):
|
||||||
|
"""
|
||||||
|
Stellar Orchard – Turn-based deterministic horticulture strategy game
|
||||||
|
Implements Stage 1 specification of "Stellar Orchard" environment.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, max_turns: int = 10):
|
||||||
|
self.max_turns = max_turns
|
||||||
|
# Grammar – exactly per Stage 1
|
||||||
|
self.patterns = {
|
||||||
|
"Plant": re.compile(r"^Plant:(A[1-5]|B[1-5])$"),
|
||||||
|
"Nurture": re.compile(r"^Nurture:(A[1-5]|B[1-5])$"),
|
||||||
|
"Harvest": re.compile(r"^Harvest:(A[1-5]|B[1-5])$"),
|
||||||
|
"Pass": re.compile(r"^Pass$"),
|
||||||
|
}
|
||||||
|
self.weather_types = ["Radiant Skies", "Lunar Mist", "Crystal Winds"]
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
# Helper: Extract boxed content
|
||||||
|
def _extract_answer_content(self, action: str) -> str:
|
||||||
|
"""Extract literal content inside \\boxed{{...}}."""
|
||||||
|
match = re.search(r"\\boxed\{\{(.*?)\}\}", action, re.DOTALL)
|
||||||
|
if match:
|
||||||
|
return match.group(1).strip()
|
||||||
|
# fallback to direct content
|
||||||
|
return action.strip()
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
def reset(self, num_players: int, seed: Optional[int] = None):
|
||||||
|
"""
|
||||||
|
Resets the environment to an initial state.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
num_players: Must be 2 for Stellar Orchard.
|
||||||
|
seed: Optional deterministic seed.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
None
|
||||||
|
"""
|
||||||
|
if num_players != 2:
|
||||||
|
raise ValueError("Stellar Orchard requires exactly 2 players.")
|
||||||
|
|
||||||
|
self.state = ta.TwoPlayerState(num_players=num_players, seed=seed, max_turns=self.max_turns, error_allowance=1)
|
||||||
|
random.seed(seed)
|
||||||
|
|
||||||
|
# deterministic environment setup
|
||||||
|
soil_fertility = {f"A{i}": random.uniform(0.5, 1.0) for i in range(1, 6)}
|
||||||
|
soil_fertility.update({f"B{i}": random.uniform(0.5, 1.0) for i in range(1, 6)})
|
||||||
|
weather_pattern = self.weather_types[seed % len(self.weather_types)] if seed is not None else random.choice(self.weather_types)
|
||||||
|
|
||||||
|
plots: Dict[str, Dict[str, Any]] = {}
|
||||||
|
for pid, owner in [("A", "A"), ("B", "B")]:
|
||||||
|
for i in range(1, 6):
|
||||||
|
plots[f"{pid}{i}"] = {"owner": owner, "status": "empty", "growth_level": 0}
|
||||||
|
|
||||||
|
game_state = {
|
||||||
|
"turn_number": 0,
|
||||||
|
"max_turns": self.max_turns,
|
||||||
|
"active_player": "Solar Gardener",
|
||||||
|
"plots": plots,
|
||||||
|
"energy_points": {"A": 0, "B": 0},
|
||||||
|
"soil_fertility": soil_fertility,
|
||||||
|
"weather_pattern": weather_pattern,
|
||||||
|
"transcript": [],
|
||||||
|
"winner": None,
|
||||||
|
"random_seed": seed if seed is not None else random.randint(0, 100000),
|
||||||
|
}
|
||||||
|
|
||||||
|
role_mapping = {0: "Solar Gardener", 1: "Lunar Gardener"}
|
||||||
|
self.state.reset(game_state=game_state, player_prompt_function=self._generate_player_prompt, role_mapping=role_mapping)
|
||||||
|
|
||||||
|
self.state.add_observation("Welcome to Stellar Orchard!", ta.ObservationType.GAME_MESSAGE)
|
||||||
|
self.state.add_observation(f"Weather pattern: {weather_pattern}", ta.ObservationType.GAME_MESSAGE)
|
||||||
|
return None
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
def _generate_player_prompt(self, player_id: int, game_state: Dict[str, Any]) -> str:
|
||||||
|
"""Construct a prompt for a player according to design spec."""
|
||||||
|
role = "Solar Gardener" if player_id == 0 else "Lunar Gardener"
|
||||||
|
player_key = "A" if player_id == 0 else "B"
|
||||||
|
opposite_key = "B" if player_id == 0 else "A"
|
||||||
|
|
||||||
|
# summarize plots
|
||||||
|
plot_summary = "\n".join(
|
||||||
|
[f"{pid}: {info['status']} (growth {info['growth_level']})" for pid, info in game_state["plots"].items() if info["owner"] == player_key]
|
||||||
|
)
|
||||||
|
|
||||||
|
soil_summary = ", ".join([f"{pid}:{game_state['soil_fertility'][pid]:.2f}" for pid in game_state["soil_fertility"] if pid.startswith(player_key)])
|
||||||
|
|
||||||
|
ep = game_state["energy_points"][player_key]
|
||||||
|
weather = game_state["weather_pattern"]
|
||||||
|
remaining_turns = game_state["max_turns"] - game_state["turn_number"]
|
||||||
|
|
||||||
|
valid_actions = (
|
||||||
|
"Possible actions this turn:\n"
|
||||||
|
" - Plant:<plot>\n"
|
||||||
|
" - Nurture:<plot>\n"
|
||||||
|
" - Harvest:<plot>\n"
|
||||||
|
" - Pass"
|
||||||
|
)
|
||||||
|
|
||||||
|
instr = (
|
||||||
|
f"You are the {role}, a cosmic horticulturist tending glowing alien trees on Selora.\n"
|
||||||
|
f"Your goal is to maximize Energy Points (EP) by cultivating your plots before the season ends.\n\n"
|
||||||
|
f"Current Weather: {weather}\n"
|
||||||
|
f"Soil Fertility (your plots): {soil_summary}\n"
|
||||||
|
f"Your Energy Points: {ep}\n"
|
||||||
|
f"Your Orchard Status:\n{plot_summary}\n\n"
|
||||||
|
f"Turn: {game_state['turn_number']} | Remaining turns: {remaining_turns}\n\n"
|
||||||
|
f"{valid_actions}\n\n"
|
||||||
|
"Put your final answer within \\boxed{{}} at the end of your response.\n\n"
|
||||||
|
"Example valid response:\n"
|
||||||
|
"I will plant my first tree in A2.\n"
|
||||||
|
"\\boxed{{Plant:A2}}\n\n"
|
||||||
|
"Example invalid response:\n"
|
||||||
|
"Let's go!\n"
|
||||||
|
"\\boxed{{Grow:A2}} # Invalid keyword"
|
||||||
|
)
|
||||||
|
|
||||||
|
return instr
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
def step(self, action: str) -> Tuple[bool, ta.Info]:
|
||||||
|
"""
|
||||||
|
Perform a single turn step with validation and deterministic game update.
|
||||||
|
"""
|
||||||
|
player_id = self.state.current_player_id
|
||||||
|
player_symbol = "A" if player_id == 0 else "B"
|
||||||
|
role_name = "Solar Gardener" if player_symbol == "A" else "Lunar Gardener"
|
||||||
|
|
||||||
|
self.state.add_observation(action, ta.ObservationType.PLAYER_ACTION, from_id=player_id, to_id=-1)
|
||||||
|
game_state = self.state.game_state
|
||||||
|
|
||||||
|
literal = self._extract_answer_content(action)
|
||||||
|
|
||||||
|
# record transcript
|
||||||
|
game_state["transcript"].append({"player": player_symbol, "action": literal})
|
||||||
|
|
||||||
|
# validation
|
||||||
|
valid_type = None
|
||||||
|
for k, pat in self.patterns.items():
|
||||||
|
if pat.match(literal):
|
||||||
|
valid_type = k
|
||||||
|
break
|
||||||
|
if valid_type is None:
|
||||||
|
self.state.set_invalid_move(reason="Invalid format")
|
||||||
|
return self.state.step()
|
||||||
|
|
||||||
|
# process the deterministic mechanics
|
||||||
|
plots = game_state["plots"]
|
||||||
|
action_valid = True
|
||||||
|
reason_if_invalid = ""
|
||||||
|
target_plot = None
|
||||||
|
if valid_type != "Pass":
|
||||||
|
target_plot = literal.split(":")[1]
|
||||||
|
|
||||||
|
if not target_plot.startswith(player_symbol):
|
||||||
|
action_valid = False
|
||||||
|
reason_if_invalid = "Plot not owned by player."
|
||||||
|
|
||||||
|
if not action_valid:
|
||||||
|
self.state.set_invalid_move(reason=reason_if_invalid)
|
||||||
|
return self.state.step()
|
||||||
|
|
||||||
|
# Logic for each action type
|
||||||
|
if valid_type == "Plant":
|
||||||
|
plot = plots[target_plot]
|
||||||
|
if plot["status"] != "empty":
|
||||||
|
self.state.set_invalid_move(reason="Plot already occupied.")
|
||||||
|
return self.state.step()
|
||||||
|
plot["status"] = "seedling"
|
||||||
|
plot["growth_level"] = 1
|
||||||
|
elif valid_type == "Nurture":
|
||||||
|
plot = plots[target_plot]
|
||||||
|
if plot["status"] not in ["seedling", "growing"]:
|
||||||
|
self.state.set_invalid_move(reason="No tree to nurture.")
|
||||||
|
return self.state.step()
|
||||||
|
if plot["growth_level"] >= 3:
|
||||||
|
self.state.set_invalid_move(reason="Tree already fully grown.")
|
||||||
|
return self.state.step()
|
||||||
|
plot["growth_level"] += 1
|
||||||
|
plot["status"] = "grown" if plot["growth_level"] >= 3 else "growing"
|
||||||
|
elif valid_type == "Harvest":
|
||||||
|
plot = plots[target_plot]
|
||||||
|
if plot["status"] != "grown":
|
||||||
|
self.state.set_invalid_move(reason="Tree not ready to harvest.")
|
||||||
|
return self.state.step()
|
||||||
|
# deterministic energy gain
|
||||||
|
gain = int(10 * game_state["soil_fertility"][target_plot])
|
||||||
|
game_state["energy_points"][player_symbol] += gain
|
||||||
|
plot["status"] = "harvested"
|
||||||
|
plot["growth_level"] = 0
|
||||||
|
elif valid_type == "Pass":
|
||||||
|
pass # nothing else happens
|
||||||
|
|
||||||
|
# increment turn number
|
||||||
|
game_state["turn_number"] += 1
|
||||||
|
game_state["active_player"] = "Solar Gardener" if player_symbol == "B" else "Lunar Gardener"
|
||||||
|
|
||||||
|
# terminal checks
|
||||||
|
if self._check_terminal_conditions():
|
||||||
|
return self.state.step()
|
||||||
|
|
||||||
|
done, info = self.state.step()
|
||||||
|
return done, info
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
def _check_terminal_conditions(self) -> bool:
|
||||||
|
"""Check game end (turn limit or all plots empty/harvested) and set outcome."""
|
||||||
|
game_state = self.state.game_state
|
||||||
|
if self.state.done:
|
||||||
|
return True
|
||||||
|
|
||||||
|
plots = game_state["plots"]
|
||||||
|
all_passive = all(p["status"] in ["empty", "harvested"] for p in plots.values())
|
||||||
|
if all_passive or game_state["turn_number"] >= game_state["max_turns"]:
|
||||||
|
ep = game_state["energy_points"]
|
||||||
|
if ep["A"] == ep["B"]:
|
||||||
|
self.state.set_draw(reason="Equal Energy Points. Draw.")
|
||||||
|
else:
|
||||||
|
winner = 0 if ep["A"] > ep["B"] else 1
|
||||||
|
self.state.set_winner(player_id=winner, reason=f"Player {winner} had more Energy Points.")
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
def get_observation(self) -> Tuple[int, List]:
|
||||||
|
"""Return current player's observation tuple."""
|
||||||
|
return self.state.current_player_id, self.state.observations
|
||||||
|
|
||||||
|
def close(self) -> Tuple[Dict, Dict]:
|
||||||
|
"""Finalize episode outputs."""
|
||||||
|
return self.state.rewards, self.state.game_info
|
||||||
|
```
|
||||||
14
pyproject.toml
Normal file
14
pyproject.toml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# pyproject.toml
|
||||||
|
|
||||||
|
[project]
|
||||||
|
name = "game_20251121_082111"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "TURN-BASED GAME DESIGN DOCUMENT environment generated for TextArena."
|
||||||
|
dependencies = [
|
||||||
|
"textarena>=0.7.3"
|
||||||
|
]
|
||||||
|
|
||||||
|
[openverse]
|
||||||
|
entry_point = "env:StellarOrchardEnv"
|
||||||
|
tags = ["openverse", "generated"]
|
||||||
|
author = "Openverse"
|
||||||
Reference in New Issue
Block a user