Files
moonchess/tests/test_game.py
T
tukaunuandClaude Opus 5.5 c52f30dc59 Moonchess: vanishing tic-tac-toe, online and practice modes
Online play over WebSockets with any-string game codes, seats and spectators,
and a 1-second heartbeat. Practice mode against Columbina, backed by a full
solver, with an accuracy slider, spoilers, undo and piece freshness.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 03:36:46 +02:00

93 lines
3.3 KiB
Python

import unittest
from game import Game
def play_all(game, cells):
for cell in cells:
err = game.play(game.turn, cell)
assert err is None, (cell, err)
class GameTest(unittest.TestCase):
def test_plain_win(self):
g = Game()
play_all(g, [0, 3, 1, 4, 2])
self.assertEqual(g.winner, 0)
self.assertEqual(g.win_line, [0, 1, 2])
def test_oldest_vanishes_as_turn_starts(self):
g = Game()
play_all(g, [0, 8, 1, 7, 5]) # X: 0,1,5 O: 8,7
self.assertEqual(g.doomed(), 0) # X's oldest, dimmed during O's turn
play_all(g, [3]) # O: 8,7,3; X's turn starts
self.assertIsNone(g.board[0])
self.assertEqual(g.history[0], [1, 5])
self.assertEqual(g.doomed(), 8) # O's oldest is next
def test_can_place_where_own_piece_vanished(self):
g = Game()
play_all(g, [0, 8, 1, 7, 5, 3])
self.assertIsNone(g.play(0, 0))
self.assertEqual(g.history[0], [1, 5, 0])
self.assertIsNone(g.board[8]) # and O's 8 went as O's turn started
def test_opponents_dimmed_piece_is_taken(self):
g = Game()
play_all(g, [0, 8, 1, 7, 5, 3])
self.assertEqual(g.play(0, 8), "That square is taken")
def test_vanishing_piece_does_not_count_toward_win(self):
g = Game()
# X: 0, 4, 2 ... then 1 would make 0-1-2, but 0 vanishes when 1 is placed.
play_all(g, [0, 3, 4, 6, 2, 7])
self.assertIsNone(g.board[0])
play_all(g, [1])
self.assertIsNone(g.winner)
self.assertEqual(g.history[0], [4, 2, 1])
def test_win_with_rotated_pieces(self):
g = Game()
play_all(g, [0, 3, 1, 4, 8, 6]) # X: 0,1,8 O: 3,4,6
play_all(g, [2]) # X: 1,8,2 (0 vanished) -> no line
self.assertIsNone(g.winner)
play_all(g, [5]) # O: 4,6,5 (3 vanished)
play_all(g, [0]) # X: 8,2,0 (1 vanished)
play_all(g, [3]) # O: 6,5,3 (4 vanished)
play_all(g, [4]) # X: 2,0,4 (8 vanished)
play_all(g, [7]) # O: 5,3,7 (6 vanished)
play_all(g, [6]) # X: 0,4,6 (2 vanished)
self.assertIsNone(g.winner)
play_all(g, [8]) # O: 3,7,8 (5 vanished)
play_all(g, [2]) # X: 4,6,2 (0 vanished) -> diagonal 2-4-6
self.assertEqual(g.winner, 0)
self.assertEqual(g.win_line, [2, 4, 6])
def test_rejects_bad_moves(self):
g = Game()
self.assertEqual(g.play(1, 0), "Not your turn")
self.assertEqual(g.play(0, 9), "Invalid square")
self.assertEqual(g.play(0, "3"), "Invalid square")
play_all(g, [4])
self.assertEqual(g.play(1, 4), "That square is taken")
def test_rematch_needs_both_and_alternates_first(self):
g = Game()
play_all(g, [0, 3, 1, 4, 2])
g.vote_rematch(0)
self.assertEqual(g.winner, 0)
g.vote_rematch(1)
self.assertIsNone(g.winner)
self.assertEqual(g.board, [None] * 9)
self.assertEqual(g.turn, 1)
def test_rematch_ignored_mid_round(self):
g = Game()
g.vote_rematch(0)
g.vote_rematch(1)
self.assertEqual(g.first, 0)
if __name__ == "__main__":
unittest.main()