* Game and supporting classes *
*********************************************************/
+const scribe_glyphs = [
+ {
+ name: "Single",
+ squares: [1,0,0,
+ 0,0,0,
+ 0,0,0]
+ },
+ {
+ name: "Double",
+ squares: [1,1,0,
+ 0,0,0,
+ 0,0,0]
+ },
+ {
+ name: "Line",
+ squares: [1,1,1,
+ 0,0,0,
+ 0,0,0]
+ },
+ {
+ name: "Pipe",
+ squares: [0,0,1,
+ 1,1,1,
+ 0,0,0]
+ },
+ {
+ name: "Squat-T",
+ squares: [1,1,1,
+ 0,1,0,
+ 0,0,0]
+ },
+ {
+ name: "4-block",
+ squares: [1,1,0,
+ 1,1,0,
+ 0,0,0]
+ },
+ {
+ name: "T",
+ squares: [1,1,1,
+ 0,1,0,
+ 0,1,0]
+ },
+ {
+ name: "Cross",
+ squares: [0,1,0,
+ 1,1,1,
+ 0,1,0]
+ },
+ {
+ name: "6-block",
+ squares: [1,1,1,
+ 1,1,1,
+ 0,0,0]
+ },
+ {
+ name: "Bomber",
+ squares: [1,1,1,
+ 0,1,1,
+ 0,0,1]
+ },
+ {
+ name: "Chair",
+ squares: [0,0,1,
+ 1,1,1,
+ 1,0,1]
+ },
+ {
+ name: "J",
+ squares: [0,0,1,
+ 1,0,1,
+ 1,1,1]
+ },
+ {
+ name: "Earring",
+ squares: [0,1,1,
+ 1,0,1,
+ 1,1,1]
+ },
+ {
+ name: "House",
+ squares: [0,1,0,
+ 1,1,1,
+ 1,1,1]
+ },
+ {
+ name: "H",
+ squares: [1,0,1,
+ 1,1,1,
+ 1,0,1]
+ },
+ {
+ name: "U",
+ squares: [1,0,1,
+ 1,0,1,
+ 1,1,1]
+ },
+ {
+ name: "Ottoman",
+ squares: [1,1,1,
+ 1,1,1,
+ 1,0,1]
+ },
+ {
+ name: "O",
+ squares: [1,1,1,
+ 1,0,1,
+ 1,1,1]
+ },
+ {
+ name: "9-block",
+ squares: [1,1,1,
+ 1,1,1,
+ 1,1,1]
+ }
+];
+
function copy_to_clipboard(id)
{
const tmp = document.createElement("input");
className += " open";
}
+ if (props.last_move) {
+ className += " last-move";
+ }
+
const onClick = props.active ? props.onClick : null;
return (
function MiniGrid(props) {
function grid_square(j) {
const value = props.squares[j];
+ const last_move = props.last_moves.includes(j);
+
+ /* Even if the grid is active, the square is only active if
+ * unoccupied. */
+ const square_active = (props.active && (value === null));
+
return (
<Square
value={value}
- active={props.active}
+ active={square_active}
+ last_move={last_move}
onClick={() => props.onClick(j)}
/>
);
}
+ /* Even if my parent thinks I'm active because of the last move, I
+ * might not _really_ be active if I'm full. */
+ let occupied = 0;
+ props.squares.forEach(element => {
+ if (element)
+ occupied++;
+ });
+
+ let class_name = "mini-grid";
+ if (props.active && occupied < 9)
+ class_name += " active";
+
return (
- <div className="mini-grid">
+ <div className={class_name}>
{grid_square(0)}
{grid_square(1)}
{grid_square(2)}
class Board extends React.Component {
mini_grid(i) {
+ /* This mini grid is active only if both:
+ *
+ * 1. It is our turn (this.props.active === true)
+ *
+ * 2. One of the following conditions is met:
+ *
+ * a. This is this players first turn (last_two_moves[0] === null)
+ * b. This mini grid corresponds to this players last turn
+ * c. The mini grid that corresponds to the players last turn is full
+ */
+ let grid_active = false;
+ if (this.props.active) {
+ grid_active = true;
+ if (this.props.last_two_moves.length > 1) {
+ /* First index (0) gives us our last move, (that is, of the
+ * last two moves, it's the first one, so two moves ago).
+ *
+ * Second index (1) gives us the second number from that move,
+ * (that is, the index within the mini-grid that we last
+ * played).
+ */
+ const target = this.props.last_two_moves[0][1];
+ let occupied = 0;
+ this.props.squares[target].forEach(element => {
+ if (element)
+ occupied++;
+ });
+ /* If the target mini-grid isn't full then this grid is
+ * only active if it is that target. */
+ if (occupied < 9)
+ grid_active = (i === target);
+ }
+ }
+
+ /* We want to highlight each of the last two moves (both "+" and
+ * "o"). So we filter the last two moves that have a first index
+ * that matches this mini_grid and pass down their second index
+ * be highlighted.
+ */
+ const last_moves = this.props.last_two_moves.filter(move => move[0] === i)
+ .map(move => move[1]);
+
const squares = this.props.squares[i];
return (
<MiniGrid
squares={squares}
- active={this.props.active}
+ active={grid_active}
+ last_moves={last_moves}
onClick={(j) => this.props.onClick(i,j)}
/>
);
player_info: {},
other_players: [],
squares: [...Array(9)].map(() => Array(9).fill(null)),
- moves: 0,
- next_to_play: "+"
+ moves: [],
+ next_to_play: "+",
};
}
}
receive_move(move) {
- if (this.state.moves === 81) {
+ if (this.state.moves.length === 81) {
return;
}
const symbol = team_symbol(this.state.next_to_play);
const new_squares = this.state.squares.map(arr => arr.slice());
new_squares[move[0]][move[1]] = symbol;
+ const new_moves = [...this.state.moves, move];
let next_to_play;
if (this.state.next_to_play === "+")
next_to_play = "o";
next_to_play = "+";
this.setState({
squares: new_squares,
- moves: this.state.moves + 1,
+ moves: new_moves,
next_to_play: next_to_play
});
}
render() {
const state = this.state;
- const first_move = state.moves === 0;
+ const first_move = state.moves.length === 0;
const my_team = state.player_info.team;
var board_active;
<Board
active={board_active}
squares={state.squares}
+ last_two_moves={state.moves.slice(-2)}
onClick={(i,j) => this.handle_click(i, j, first_move)}
/>
</div>
</div>,
<div key="glyphs" className="glyphs">
- <Glyph
- name="Single"
- squares={[1,0,0,
- 0,0,0,
- 0,0,0]}
- />
- <Glyph
- name="Double"
- squares={[1,1,0,
- 0,0,0,
- 0,0,0]}
- />
- <Glyph
- name="Line"
- squares={[1,1,1,
- 0,0,0,
- 0,0,0]}
- />
- <Glyph
- name="Pipe"
- squares={[0,0,1,
- 1,1,1,
- 0,0,0]}
- />
- <Glyph
- name="Squat-T"
- squares={[1,1,1,
- 0,1,0,
- 0,0,0]}
- />
- <Glyph
- name="4-block"
- squares={[1,1,0,
- 1,1,0,
- 0,0,0]}
- />
- <Glyph
- name="T"
- squares={[1,1,1,
- 0,1,0,
- 0,1,0]}
- />
- <Glyph
- name="Cross"
- squares={[0,1,0,
- 1,1,1,
- 0,1,0]}
- />
- <Glyph
- name="6-block"
- squares={[1,1,1,
- 1,1,1,
- 0,0,0]}
- />
- <Glyph
- name="Bomber"
- squares={[1,1,1,
- 0,1,1,
- 0,0,1]}
- />
- <Glyph
- name="Chair"
- squares={[0,0,1,
- 1,1,1,
- 1,0,1]}
- />
- <Glyph
- name="J"
- squares={[0,0,1,
- 1,0,1,
- 1,1,1]}
- />
- <Glyph
- name="Earring"
- squares={[0,1,1,
- 1,0,1,
- 1,1,1]}
- />
- <Glyph
- name="House"
- squares={[0,1,0,
- 1,1,1,
- 1,1,1]}
- />
- <Glyph
- name="H"
- squares={[1,0,1,
- 1,1,1,
- 1,0,1]}
- />
- <Glyph
- name="U"
- squares={[1,0,1,
- 1,0,1,
- 1,1,1]}
- />
- <Glyph
- name="Ottoman"
- squares={[1,1,1,
- 1,1,1,
- 1,0,1]}
- />
- <Glyph
- name="O"
- squares={[1,1,1,
- 1,0,1,
- 1,1,1]}
- />
- <Glyph
- name="9-block"
- squares={[1,1,1,
- 1,1,1,
- 1,1,1]}
- />
+ {
+ scribe_glyphs.map(glyph => {
+ return (
+ <Glyph
+ key={glyph.name}
+ name={glyph.name}
+ squares={glyph.squares}
+ />
+ );
+ })
+ }
</div>
];
}