]> git.cworth.org Git - lmno.games/blobdiff - tictactoe/tictactoe.jsx
Add a ready bit to client state, and render nothing before ready
[lmno.games] / tictactoe / tictactoe.jsx
index 49c6005c38fe395c610502853f1ec69ab28d3438..dbfc5ef93e9ba41d21f026a14653e179828fbd4a 100644 (file)
@@ -47,7 +47,7 @@ events.addEventListener("player-info", event => {
 events.addEventListener("player-enter", event => {
   const info = JSON.parse(event.data);
 
-  window.game.set_opponent_info(info);
+  window.game.set_other_player_info(info);
 });
 
 events.addEventListener("player-update", event => {
@@ -56,7 +56,7 @@ events.addEventListener("player-update", event => {
   if (info.id === window.game.state.player_info.id)
     window.game.set_player_info(info);
   else
-    window.game.set_opponent_info(info);
+    window.game.set_other_player_info(info);
 });
 
 events.addEventListener("move", event => {
@@ -91,20 +91,57 @@ function GameInfo(props) {
   );
 }
 
+function TeamButton(props) {
+  return <button className="inline"
+                 onClick={() => props.game.join_team(props.team)}>
+           {props.label}
+         </button>;
+}
+
+function TeamChoices(props) {
+  let other_team;
+  if (props.player.team === "X")
+    other_team = "O";
+  else
+    other_team = "X";
+
+  if (props.player.team === "") {
+    if (props.first_move) {
+      return null;
+    } else {
+      return [
+        <TeamButton key="X" game={props.game} team="X" label="Join X" />,
+        " ",
+        <TeamButton key="O" game={props.game} team="O" label="Join O" />
+      ];
+    }
+  } else {
+    return <TeamButton game={props.game} team={other_team} label="Switch" />;
+  }
+}
+
 function PlayerInfo(props) {
   if (! props.player.id)
     return null;
 
+  const choices = <TeamChoices
+                    game={props.game}
+                    first_move={props.first_move}
+                    player={props.player}
+                  />;
+
   return (
     <div className="player-info">
       <h2>Players</h2>
       {props.player.name}
       {props.player.team ? ` (${props.player.team})` : ""}
-      {props.opponents.map(opponent => (
-        <span key={opponent.id}>
+      {props.first_move ? "" : " "}
+      {choices}
+      {props.other_players.map(other => (
+        <span key={other.id}>
           {", "}
-          {opponent.name}
-          {opponent.team ? ` (${opponent.team})` : ""}
+          {other.name}
+          {other.team ? ` (${other.team})` : ""}
         </span>
       ))}
     </div>
@@ -190,7 +227,7 @@ class Game extends React.Component {
     this.state = {
       game_info: {},
       player_info: {},
-      opponent_info: [],
+      other_players: [],
       history: [
         {
           squares: Array(9).fill(null)
@@ -213,16 +250,16 @@ class Game extends React.Component {
     });
   }
 
-  set_opponent_info(info) {
-    const new_opponents = [...this.state.opponent_info];
-    const idx = new_opponents.findIndex(o => o.id === info.id);
+  set_other_player_info(info) {
+    const other_players_copy = [...this.state.other_players];
+    const idx = other_players_copy.findIndex(o => o.id === info.id);
     if (idx >= 0) {
-      new_opponents[idx] = info;
+      other_players_copy[idx] = info;
     } else {
-      new_opponents.push(info);
+      other_players_copy.push(info);
     }
     this.setState({
-      opponent_info: new_opponents
+      other_players: other_players_copy
     });
   }
 
@@ -305,7 +342,17 @@ class Game extends React.Component {
     }
     else if (first_move)
     {
-      status = "Either player can make the first move.";
+      if (state.other_players.length == 0) {
+        status = "You can move or wait for another player to join.";
+      } else {
+        let qualifier;
+        if (state.other_players.length == 1) {
+          qualifier = "Either";
+        } else {
+          qualifier = "Any";
+        }
+        status = `${qualifier} player can make the first move.`;
+      }
       board_active = true;
     }
     else if (my_team === "")
@@ -320,7 +367,12 @@ class Game extends React.Component {
     }
     else
     {
-      status = "Waiting for your opponent to move.";
+      status = "Waiting for another player to ";
+      if (state.other_players.length == 0) {
+        status += "join.";
+      } else {
+        status += "move.";
+      }
       board_active = false;
     }
 
@@ -332,15 +384,12 @@ class Game extends React.Component {
       />,
       <PlayerInfo
         key="player-info"
+        game={this}
+        first_move={first_move}
         player={state.player_info}
-        opponents={state.opponent_info}
+        other_players={state.other_players}
       />,
       <div key="game" className="game">
-        <button className="inline"
-                onClick={() => this.join_team('X')}>Join Team X</button>
-        {" "}
-        <button className="inline"
-                onClick={() => this.join_team('O')}>Join Team O</button>
         <div>{status}</div>
         <div className="game-board">
           <Board