A synced multiplayer Reversi (Othello) board. Made for SideQuest / AltspaceVR worlds, and it also works in Banter.
There is no server: players stay in sync through the space's shared state, and the game is plain static files served from https://reversi.firer.at.
To try it, open https://reversi.firer.at in Altspace or Banter.
- Valid moves highlighted in blue
- Turns pass automatically when a player has no move
- A floating panel showing whose turn it is, with seats, Reset and Mute
- Seat locking: claim a side so only you can move it. While a game is under way only its seated players can reset it (or anyone, once a seat is left idle or empty)
- Switches itself off when you are far away, so it costs nothing elsewhere in the world
- Several independent boards in one world
In a Creator SDK world, add an empty GameObject at the origin, click Add Component > BS > Snippet and type reversi. Or paste this into Assets/WebRoot/index.html, between the snippet section comments:
<!-- snippet section -->
<bs-snippet name="reversi" title="Reversi"
description="Synced multiplayer Reversi (Othello) board with seat locking."
script="https://reversi.firer.at/snippet.js"
room=""
position="0 1 2"
rotation="0 0 0"
scale="0.5"
lit="true"
add-lights="false"
turn-cooldown="5"
lock-timeout="90"
cull-distance="20"
sound-volume="0.4"
sound-near="2.5"
sound-far="10"
hide-ui="false"
hide-board="false"
use-custom-models="true"
scoreboard-position="0 0 0"
scoreboard-rotation="0 0 0"
scoreboard-scale="1">
<bs-gizmo type="position" attribute="position"/>
<bs-gizmo type="box" attribute="position" size="2 0.05 2"/>
</bs-snippet>
<!-- end snippet section -->- Each placement is its own game. Its sync id is
room, or the placement's own id whenroomis empty. Give placements the sameroomto share one game. positionandrotationare Unity world values, andscalecan be a single number. The other settings are listed under Settings. An empty setting uses the default.- The Scene-view gizmo shows the board at its default size; it does not follow
scale. - Unity reads the snippet section as XML: quote every attribute, close every element, and write
&as&.
This works in an Altspace world's Assets/WebRoot/index.html (outside the snippet section) and in a Banter space's HTML:
<script src="https://reversi.firer.at/Reversi.js" position="0 1.1 -2"></script>For more than one board in a space, give each one its own instance:
<script src="https://reversi.firer.at/Reversi.js" instance="board1" position="-2 1.1 -2"></script>
<script src="https://reversi.firer.at/Reversi.js" instance="board2" position="2 1.1 -2"></script>Settings can also go in the URL, as in older setups: https://reversi.firer.at/Reversi.js?boardPosition=0+1.1+-2&boardScale=0.8.
| Setting | Also accepted | Default | Description |
|---|---|---|---|
instance |
page URL | Sync id. Boards with the same id share one game. In a snippet, use room instead. |
|
boardPosition |
position, board-position |
0 1.1 -2 |
Board position (x y z). |
boardRotation |
rotation, board-rotation |
0 0 0 |
Board rotation in degrees (x y z). |
boardScale |
scale, board-scale |
1 |
Board scale: one number, or x y z. |
hideUI |
hide-ui |
false |
true hides the UI panel (turn, seats, Reset, Mute). |
scoreboardPosition |
scoreboard-position |
0 0 0 |
Position of the UI panel, relative to the board. 0 0 0 puts it just above the board. The panel turns to face each player. |
scoreboardRotation |
scoreboard-rotation |
0 0 0 |
UI panel rotation. |
scoreboardScale |
scoreboard-scale |
1 |
UI panel size: 1 is normal, 2 twice as big. It also grows with the board's scale. |
turnCooldown |
turn-cooldown |
5 |
Seconds after a move before the same person can move for the other side, so a double click or an eager player can't take the opponent's turn. Playing both sides alone still works after the wait. 0 turns it off. |
lockTimeout |
lock-timeout |
90 |
Seconds a seated player can leave their turn untouched before anyone can take their seat. A seat also frees up when its player leaves the space. 0 turns the timeout off. Unclaimed sides can be moved by anyone. |
cullDistance |
cull-distance |
20 |
Metres from the board beyond which the game switches itself off for you (board, pieces and panel), and back on when you come within a metre less. Moves made meanwhile show up when you return. 0 keeps it always on. |
volume |
sound-volume |
0.4 |
Volume of the sound effects (moves, captures, wins, resets), from 0 to 1, heard at full strength near the game. 0 turns them off. |
soundNear |
sound-near |
2.5 |
Distance in metres from the game within which the sounds play at full sound-volume. |
soundFar |
sound-far |
10 |
Distance in metres at which the sounds have faded out completely, so people elsewhere in the world aren't disturbed. |
hideBoard |
hide-board |
false |
true hides the board, e.g. to use your own. |
useCustomModels |
use-custom-models |
true |
Uses the GLB models in Models/ for the pieces. false uses built-in shapes instead. |
lit |
true |
Uses materials that react to scene lights. false uses unlit materials that ignore lighting. |
|
lighting |
lit |
Older form of lit: lit or unlit. lit wins if both are set. |
|
addLights |
add-lights |
false |
With lit="true", true adds a directional light, for worlds that have no lights of their own. |
Settings can be written as boardPosition or board-position; the snippet uses the hyphenated form.
A position of 0 0 0 means automatic: the UI panel sits just above the board. Any other value places it relative to the board.
- Black moves first.
- Click a blue square to place a piece. A move must trap at least one opponent piece between the new piece and one of yours.
- Trapped pieces flip to your colour.
- A player with no valid move is skipped.
- The game ends when neither player can move. Most pieces wins.
Reversi.js: the game.Models/: piece models foruse-custom-models.snippet.js,snippet.html: the Creator SDK snippet and its definition.index.html: a test page with a floor and the game.
GPL-3.0. See LICENSE.