Skip to content

Commit

Permalink
Merge pull request #267 from /issues/250-html-instructions
Browse files Browse the repository at this point in the history
move to html instructions
  • Loading branch information
jessesnyder authored Oct 11, 2023
2 parents 65252c2 + e22f181 commit 92dcd0d
Show file tree
Hide file tree
Showing 10 changed files with 66 additions and 203 deletions.
169 changes: 5 additions & 164 deletions dlgr/griduniverse/experiment.py
Original file line number Diff line number Diff line change
Expand Up @@ -593,171 +593,12 @@ def deserialize(self, state):
self.item_locations[tuple(obj.position)] = obj

def instructions(self):
color_costs = ""
order = ""
text = """<p>The objective of the game is to maximize your final payoff.
The game is played on a {g.columns} x {g.rows} grid, where each
player occupies one block. <br><img src='static/images/gameplay.gif'
height='150'><br>"""
if self.window_columns < self.columns or self.window_rows < self.rows:
text += """ The grid is viewed through a
{g.window_columns} x {g.window_rows} window
that moves along with your player."""
if self.walls_density > 0:
text += """ There are walls throughout the grid, which the players
cannot pass through."""
if not self.walls_visible:
text += " However, the walls are not visible."
if self.build_walls:
text += """ Players can build walls at their current position using
the 'w' key. The wall will not appear until the player has moved
away from that position."""
if self.wall_building_cost > 0:
text += """ Building a wall has a cost of {g.wall_building_cost}
points."""
if self.num_rounds > 1:
text += """ The game has {g.num_rounds} rounds, each lasting
<strong>{g.time_per_round} seconds</strong>.</p>"""
else:
text += (
" The game duration is <strong>{g.time_per_round}</strong> seconds.</p>"
)
if self.num_players > 1:
text += """<p>There are <strong>{g.num_players} players</strong> participating
in the game."""
if not self.others_visible:
text += """ However, players cannot see each other on the
grid."""
if self.num_colors > 1:
text += """ Each player will be one of {g.num_colors} available
colors ({color_list})."""
if self.mutable_colors:
text += " Players can change color using the 'c' key."
if self.costly_colors:
costs = [
"{c}, {p} points".format(c=c, p=p)
for p, c in zip(
self.color_costs, self.limited_player_color_names
)
]
color_costs = "; ".join(costs)
text += """ Changing color has a different cost in
points for each color: {color_costs}."""
if self.contagion > 0:
text += """ If a player enters a region of the grid where a
plurality of the surrounding players within {g.contagion}
blocks are of a different color, that player will take
on the color of the plurality."""
if self.contagion_hierarchy:
order = ", ".join(
[
self.limited_player_color_names[h]
for h in self.contagion_hierarchy
]
)
text += """ However, there is a hierarchy of colors, so
that only players of some colors are susceptible to
changing color in this way. The hierarchy, from
lowest to highest, is: {order}. Colors lower in the
hierarchy can be affected only by higher colors."""
if self.frequency_dependence > 0:
text += """ Players will get more points if their
color is in the majority."""
if self.frequency_dependence < 0:
text += """ Players will get more points if their
color is in the minority."""
text += """</p><p>Players move around the grid using the arrow keys.
<br><img src='static/images/keys.gif' height='60'><br>"""
if self.player_overlap:
text += " More than one player can occupy a block at the same time."
else:
text += """ A player cannot occupy a block where a player is
already present."""
if self.visibility < max(self.rows, self.columns):
text += """ Players cannot see the whole grid, but only an area
approximately {g.visibility} blocks around their current
position."""
text += """<p>Press the 'h' key to toggle highlighting of your player.
<br><img src='static/images/h-toggle.gif' height='150'><p>"""
if self.motion_auto:
text += """ Once a player presses a key to move, the player will
continue to move in the same direction automatically until
another key is pressed."""
if self.motion_cost > 0:
text += """ Each movement costs the player {g.motion_cost}
{g.motion_cost:plural, point, points}."""
if self.motion_tremble_rate > 0 and self.motion_tremble_rate < 0.4:
text += """ Some of the time, movement will not be in the chosen
direction, but random."""
if self.motion_tremble_rate >= 0.4 and self.motion_tremble_rate < 0.7:
text += """ Movement will not be in the chosen direction most of the
time, but random."""
if self.motion_tremble_rate >= 0.7:
text += """ Movement commands will be ignored almost all of the time,
and the player will move in a random direction instead."""
text += """</p><p>Players gain points by getting to squares that have
food on them. Each piece of food is worth x
points. When the game starts there
are <strong>n</strong> pieces
of food on the grid. Food is represented by a green"""

text += " or brown"
text += " square: <img src='static/images/food-green.png' height='20'>"
text += " <img src='static/images/food-brown.png' height='20'>"
text += "<br>Food can be respawned after it is consumed."

text += """It will appear immediately, but may not be consumable for
some time if it has a maturation period. It will show
up as brown initially, and then as green when it matures."""
text += """<br>The location where the food will appear after respawning is
is determined by the <strong>configured</strong>
probability distribution for each item type."""
text += " Players may be able to plant more food by pressing the spacebar."
text += "</p>"
if self.alternate_consumption_donation and self.num_rounds > 1:
text += """<p> Rounds will alternate between <strong>consumption</strong> and
<strong>donation</strong> rounds. Consumption rounds will allow for free movement
on the grid. Donation rounds will disable movement and allow you to donate points.</p>
"""
if self.donation_amount > 0:
text += """<img src='static/images/donate-click.gif' height='210'><br>
<p>It can be helpful to donate points to others.
"""
if self.donation_individual:
text += """ You can donate <strong>{g.donation_amount}</strong>
{g.donation_amount:plural, point, points} to any player by clicking on
<img src='static/images/donate-individual.png' class='donate'
height='30'>, then clicking on their block on the grid.
"""
if self.donation_group:
text += """ To donate to a group, click on the
<img src='static/images/donate-group.png' class='donate' height='30'>
button, then click on any player with the color of the team
you want to donate to.
"""
if self.donation_public:
text += """ The <img src='static/images/donate-public.png'
class='donate' height='30'> button splits your donation amongst
every player in the game (including yourself).
"""
text += "</p>"
if self.show_chatroom:
text += """<p>A chatroom is available to send messages to the other
players."""
if self.pseudonyms:
text += """ Player names shown on the chat window are pseudonyms.
<br><img src='static/images/chatroom.gif' height='150'>"""
text += "</p>"
if self.dollars_per_point > 0:
text += """<p>You will receive <strong>${g.dollars_per_point}</strong> for each point
that you score at the end of the game.</p>"""
return formatter.format(
text,
g=self,
order=order,
color_costs=color_costs,
color_list=", ".join(self.limited_player_color_names),
instructions_file_path = os.path.join(
os.path.dirname(__file__), "templates/instructions/instruct-ready.html"
)
with open(instructions_file_path) as instructions_file:
instructions_html = instructions_file.read()
return instructions_html

def consume(self):
"""Players consume the non-interactive items"""
Expand Down
33 changes: 0 additions & 33 deletions dlgr/griduniverse/game_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -176,39 +176,6 @@ transition_defaults:
modify_uses: [0, 0]

items:
# Legacy GU Food item
- item_id: food
calories: 5
crossable: true
interactive: false
maturation_speed: 0.1
maturation_threshold: 0.5
n_uses: 1
name: Food
plantable: false
planting_cost: 1
portable: true
respawn: true
item_count: 8
limit_quantity: true
sprite: "color:#8a9b0f,#7a6b54"

- item_id: food2
calories: 3
crossable: true
interactive: false
item_count: 50
maturation_speed: 0.2
maturation_threshold: 0.5
n_uses: 1
name: Food2
plantable: false
planting_cost: 1
portable: true
respawn: true
limit_quantity: true
sprite: "image:sprites/food.png"

# One Hour, One Life items
- crossable: true
interactive: true
Expand Down
Binary file removed dlgr/griduniverse/static/images/gameplay.gif
Binary file not shown.
Binary file added dlgr/griduniverse/static/images/gameplay.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed dlgr/griduniverse/static/images/h-toggle.gif
Binary file not shown.
Binary file added dlgr/griduniverse/static/images/h-toggle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dlgr/griduniverse/static/images/stone.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
58 changes: 58 additions & 0 deletions dlgr/griduniverse/templates/instructions/instruct-ready.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<p>
The objective of the game is to maximize your final payoff.
The game is played on a 200 x 100 grid, where each
player occupies one block.<br>
<img src="./static/images/gameplay.png" height="250"><br>
The grid is viewed through a 20 x 20 window
that moves along with your player. The game has 3 rounds, each lasting
<strong>45.0 seconds</strong>.
</p>
<p>
Players move around the grid using the arrow keys.<br>
<img src="./static/images/keys.gif" height="60"><br>
A player cannot occupy a block where a player is
already present. Players cannot see the whole grid, but only an area
approximately 40 blocks around their current position.
</p>
<p>
Press the 'h' key to toggle highlighting of your player.<br>
<img src="./static/images/h-toggle.png" height="250">
</p>
<p>
Players gain points by picking up and eating edible items:
<ul>
<li>🥕 Wild Carrot (5 points)</li>
<li>🫐 Gooseberry (3 points)</li>
</ul>
Once a food item is being carried, pressing the spacebar causes
it to be eaten, which awards the points to the player.
</p>
<p>
The edible items do not exist on the board at the start of play.
Players must produce them by picking up other objects and carrying out
"transitions" to transform them, or by reaching a specific object and
triggering the transition.
</p>
It is possible for the players to transform some items into food
in various ways:
<ul>
<li>Pick up a 💎 Sharp Stone and press the spacebar while
occupying the same square as a 🥕 Wild Carrot Plant.</li>
<li>Occupy same square as a 🌴 Gooseberry Bush and press spacebar to
eat a 🫐 Gooseberry. Gooseberry bushes have only 6 berries each.
Once all berries are eaten, the bush is empty and players can't
occupy the bush's square anymore.</li>
<li>If there are no 💎 Sharp Stones on the grid, players can create
one by picking up a <img src="./static/images/stone.png" width="16">
Stone, going to a 🗿 Big Hard Rock, and pressing the spacebar.</li>
</ul>
</p>
<p>
A chatroom is available to send messages to the other
players. Player names shown on the chat window are pseudonyms.<br>
<img src="./static/images/chatroom.gif" height="150">
</p>
<p>
You will receive <strong>$0.02</strong> for each point
that you score at the end of the game.
</p>
4 changes: 2 additions & 2 deletions test/test_griduniverse.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@ def test_new_experiment_has_item_config_with_defaults(self, exp):
item_config = exp.item_config
assert isinstance(item_config, dict)
# We define a Food item, and pull the null public good multiplier from the default
assert item_config["food"]["name"] == "Food"
assert item_config["food"]["public_good_multiplier"] == 0.0
assert item_config["stone"]["name"] == "Stone"
assert item_config["stone"]["public_good_multiplier"] == 0.0

def test_new_experiment_has_transition_config_with_defaults(self, exp):
transition_config = exp.transition_config
Expand Down
5 changes: 1 addition & 4 deletions test/test_gridworld.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,4 @@ class TestInstructions(object):
def test_instructions(self, gridworld):
# Just test something basic
html = gridworld.instructions()
assert (
f"game duration is <strong>{gridworld.time_per_round}</strong> seconds"
in html
)
assert "🫐 Gooseberry (3 points)" in html

0 comments on commit 92dcd0d

Please sign in to comment.