diff --git a/tictactoe/__init__.py b/tictactoe/__init__.py
deleted file mode 100644
index e5664bc..0000000
--- a/tictactoe/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from .plugin import TictactoePlugin
diff --git a/tictactoe/config_dialog.py b/tictactoe/config_dialog.py
deleted file mode 100644
index 9ff4f02..0000000
--- a/tictactoe/config_dialog.py
+++ /dev/null
@@ -1,55 +0,0 @@
-#
-# This file is part of the TicTacToe plugin for Gajim.
-#
-# Gajim is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Gajim is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Gajim. If not, see .
-
-from gi.repository import GObject
-from gi.repository import Gtk
-
-from gajim.gui.settings import SettingsDialog
-from gajim.gui.settings import SpinSetting
-from gajim.gui.const import Setting
-from gajim.gui.const import SettingType
-
-from gajim.plugins.plugins_i18n import _
-
-
-class TicTacToeConfigDialog(SettingsDialog):
- def __init__(self, plugin, parent):
-
- self.plugin = plugin
- settings = [
- Setting('BoardSizeSpinSetting', _('Board Size'),
- SettingType.VALUE, self.plugin.config['board_size'],
- callback=self.on_setting, data='board_size',
- desc=_('Size of the board'),
- props={'range_': (3, 10)})]
-
- SettingsDialog.__init__(self, parent, _('TicTacToe Configuration'),
- Gtk.DialogFlags.MODAL, settings, None,
- extend=[
- ('BoardSizeSpinSetting', SizeSpinSetting)])
-
- def on_setting(self, value, data):
- self.plugin.config[data] = value
-
-
-class SizeSpinSetting(SpinSetting):
-
- __gproperties__ = {
- "setting-value": (int, 'Size', '', 3, 10, 3,
- GObject.ParamFlags.READWRITE), }
-
- def __init__(self, *args, **kwargs):
- SpinSetting.__init__(self, *args, **kwargs)
diff --git a/tictactoe/manifest.ini b/tictactoe/manifest.ini
deleted file mode 100644
index 23a3166..0000000
--- a/tictactoe/manifest.ini
+++ /dev/null
@@ -1,9 +0,0 @@
-[info]
-name: Tic tac toe
-short_name: tictactoe
-version: 1.8.2
-description: Play Tic-tac-toe.
-authors = Yann Leboulanger
-homepage = https://dev.gajim.org/gajim/gajim-plugins/wikis/TictactoePlugin
-min_gajim_version: 1.4.0-dev1
-max_gajim_version: 1.4.90
diff --git a/tictactoe/plugin.py b/tictactoe/plugin.py
deleted file mode 100644
index 487368b..0000000
--- a/tictactoe/plugin.py
+++ /dev/null
@@ -1,784 +0,0 @@
-#
-# Copyright (C) 2011 Yann Leboulanger
-#
-# This file is part of the TicTacToe plugin for Gajim.
-#
-# Gajim is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published
-# by the Free Software Foundation; version 3 only.
-#
-# Gajim is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Gajim. If not, see .
-#
-
-'''
-Tictactoe plugin.
-
-:author: Yann Leboulanger
-:since: 21 November 2011
-:copyright: Copyright (2011) Yann Leboulanger
-:license: GPL
-'''
-
-import string
-import itertools
-import random
-
-from functools import partial
-
-from gi.repository import Gtk
-from gi.repository import Gdk
-from gi.repository import Gio
-from gi.repository import GLib
-
-import nbxmpp
-
-from gajim.common import app
-from gajim.common import ged
-from gajim.common.connection_handlers_events import InformationEvent
-
-from gajim.gui.dialogs import DialogButton
-from gajim.gui.dialogs import ConfirmationDialog
-
-from gajim.plugins import GajimPlugin
-from gajim.plugins.helpers import log
-from gajim.plugins.helpers import log_calls
-from gajim.plugins.plugins_i18n import _
-
-from tictactoe.config_dialog import TicTacToeConfigDialog
-
-try:
- import gi
- gi.require_version('PangoCairo', '1.0')
- from gi.repository import PangoCairo
- HAS_PANGOCAIRO = True
-except ImportError:
- HAS_PANGOCAIRO = False
-
-NS_GAMES = 'http://jabber.org/protocol/games'
-NS_GAMES_TICTACTOE = NS_GAMES + '/tictactoe'
-
-
-class TictactoePlugin(GajimPlugin):
- @log_calls('TictactoePlugin')
- def init(self):
- if not HAS_PANGOCAIRO:
- self.activatable = False
- self.config_dialog = None
- self.available_text = _('TicTacToe requires PangoCairo to run')
- self.description = _('Play Tictactoe.')
- self.config_dialog = partial(TicTacToeConfigDialog, self)
- self.events_handlers = {
- 'decrypted-message-received': (
- ged.PREGUI, self._on_message_received),
- }
-
- self.gui_extension_points = {
- 'chat_control': (self.connect_with_chat_control,
- self.disconnect_from_chat_control),
- 'chat_control_base_update_toolbar': (
- self.update_button_state, None),
- 'update_caps': (self._update_caps, None),
- }
-
- self.config_default_values = {
- 'board_size': (5, ''),
- }
-
- self.controls = []
- self.announce_caps = True
-
- @log_calls('TictactoePlugin')
- def _update_caps(self, _account, features):
- if not self.announce_caps:
- return
-
- features.append(NS_GAMES)
- features.append(NS_GAMES_TICTACTOE)
-
- @log_calls('TictactoePlugin')
- def activate(self):
- self.announce_caps = True
- for con in app.connections.values():
- con.get_module('Caps').update_caps()
-
- @log_calls('TictactoePlugin')
- def deactivate(self):
- self.announce_caps = False
- for con in app.connections.values():
- con.get_module('Caps').update_caps()
-
- @log_calls('TictactoePlugin')
- def connect_with_chat_control(self, control):
- if not control.is_chat:
- return
-
- base = Base(self, control)
- self.controls.append(base)
- # Already existing session?
- conn = app.connections[control.account]
- sessions = conn.get_sessions(control.contact.jid)
- tictactoes = [s for s in sessions if isinstance(
- s, TicTacToeSession)]
- if tictactoes:
- base.tictactoe = tictactoes[0]
- base.enable_action(True)
-
- @log_calls('TictactoePlugin')
- def disconnect_from_chat_control(self, _chat_control):
- for base in self.controls:
- base.disconnect_from_chat_control()
- self.controls = []
-
- @log_calls('TictactoePlugin')
- def update_button_state(self, control):
- for base in self.controls:
- if base.chat_control == control:
- if (control.contact.supports(NS_GAMES) and
- control.contact.supports(NS_GAMES_TICTACTOE)):
- base.enable_action(True)
- else:
- base.enable_action(False)
-
- @log_calls('TictactoePlugin')
- def show_request_dialog(self, obj, session):
- def _on_accept():
- session.invited(obj.stanza)
-
- def _on_decline():
- session.decline_invitation()
-
- account = obj.conn.name
- client = app.get_client(account)
- contact = client.get_module('Contacts').get_contact(obj.jid)
-
- ConfirmationDialog(
- _('Incoming Tictactoe'),
- _('Incoming Tictactoe Invitation'),
- _('%(name)s (%(jid)s) wants to play tictactoe with you.') % {
- 'name': contact.name, 'jid': obj.jid},
- [DialogButton.make('Cancel',
- text=_('_Decline'),
- callback=_on_decline),
- DialogButton.make('OK',
- text=_('_Accept'),
- callback=_on_accept)],
- modal=False,
- transient_for=app.window).show()
-
- @log_calls('TictactoePlugin')
- def _on_message_received(self, event):
- if isinstance(event.session, TicTacToeSession):
- event.session.received(event.stanza)
- game_invite = event.stanza.getTag('invite', namespace=NS_GAMES)
- if game_invite:
- game = game_invite.getTag('game')
- if game and game.getAttr('var') == NS_GAMES_TICTACTOE:
- session = event.conn.make_new_session(
- event.fjid, event.properties.thread, cls=TicTacToeSession)
- self.show_request_dialog(event, session)
-
-
-class Base():
- def __init__(self, plugin, chat_control):
- self.plugin = plugin
- self.chat_control = chat_control
- self.contact = self.chat_control.contact
- self.account = self.chat_control.account
- self.fjid = self.contact.jid
- self.add_action()
- self.tictactoe = None
-
- def add_action(self):
- action_name = 'toggle-tictactoe-' + self.chat_control.control_id
- act = Gio.SimpleAction.new_stateful(
- action_name, None, GLib.Variant.new_boolean(False))
- act.connect('change-state', self.on_tictactoe_button_toggled)
- app.window.add_action(act)
-
- self.chat_control.control_menu.append(
- 'Tic Tac Toe', 'win.' + action_name)
-
- def enable_action(self, state):
- action_name = 'toggle-tictactoe-' + self.chat_control.control_id
- app.window.lookup_action(action_name).set_enabled(state)
-
- def on_tictactoe_button_toggled(self, action, param):
- """
- Popup whiteboard
- """
- action.set_state(param)
- state = param.get_boolean()
- if state:
- if not self.tictactoe:
- self.start_tictactoe()
- else:
- self.stop_tictactoe('resign')
-
- def start_tictactoe(self):
- self.tictactoe = app.connections[self.account].make_new_session(
- self.fjid, cls=TicTacToeSession)
- self.tictactoe.base = self
- self.tictactoe.begin()
-
- def stop_tictactoe(self, reason=None):
- self.tictactoe.end_game(reason)
- if hasattr(self.tictactoe, 'board'):
- self.tictactoe.board.win.destroy()
- self.tictactoe = None
-
- def disconnect_from_chat_control(self):
- menu = self.chat_control.control_menu
- for item in range(menu.get_n_items()):
- label = menu.get_item_attribute_value(item, 'label')
- if label.get_string() == 'Tic Tac Toe':
- menu.remove(item)
- break
-
-
-class InvalidMove(Exception):
- pass
-
-
-class TicTacToeSession():
- def __init__(self, conn, jid, thread_id, type_):
- self.conn = conn
- self.jid = jid
- self.type_ = type_
- self.resource = jid.resource
-
- if thread_id:
- self.received_thread_id = True
- self.thread_id = thread_id
- else:
- self.received_thread_id = False
- self.thread_id = self.generate_thread_id()
-
- client = app.get_client(conn.name)
- contact = client.get_module('Contacts').get_contact(jid)
- self.name = contact.name
- self.base = None
- self.control = None
- self.enable_encryption = False
-
- @staticmethod
- def is_loggable():
- return False
-
- def send(self, msg):
- if self.thread_id:
- msg.NT.thread = self.thread_id
-
- msg.setAttr('to', self.get_to())
- self.conn.send_stanza(msg)
-
- def get_to(self):
- to = str(self.jid)
- jid = app.get_jid_without_resource(to)
- if self.resource:
- jid += '/' + self.resource
- return jid
-
- @staticmethod
- def generate_thread_id():
- return ''.join(
- [f(string.ascii_letters) for f in itertools.repeat(
- random.choice, 32)]
- )
-
- # Initiate a session
- def begin(self, role_s='x'):
- self.rows = self.base.plugin.config['board_size']
- self.cols = self.base.plugin.config['board_size']
-
- self.role_s = role_s
-
- self.strike = self.base.plugin.config['board_size']
-
- if self.role_s == 'x':
- self.role_o = 'o'
- else:
- self.role_o = 'x'
-
- self.send_invitation()
-
- self.next_move_id = 1
- self.received = self.wait_for_invite_response
-
- def send_invitation(self):
- msg = nbxmpp.Message()
-
- invite = msg.NT.invite
- invite.setNamespace(NS_GAMES)
- invite.setAttr('type', 'new')
-
- game = invite.NT.game
- game.setAttr('var', NS_GAMES_TICTACTOE)
-
- x = nbxmpp.DataForm(typ='submit')
- f = x.setField('role')
- f.setType('list-single')
- f.setValue('x')
- f = x.setField('rows')
- f.setType('text-single')
- f.setValue(str(self.base.plugin.config['board_size']))
- f = x.setField('cols')
- f.setType('text-single')
- f.setValue(str(self.base.plugin.config['board_size']))
- f = x.setField('strike')
- f.setType('text-single')
- f.setValue(str(self.base.plugin.config['board_size']))
-
- game.addChild(node=x)
-
- self.send(msg)
-
- def read_invitation(self, msg):
- invite = msg.getTag('invite', namespace=NS_GAMES)
- game = invite.getTag('game')
- x = game.getTag('x', namespace='jabber:x:data')
-
- form = nbxmpp.DataForm(node=x)
-
- if form.getField('role'):
- self.role_o = form.getField('role').getValues()[0]
- else:
- self.role_o = 'x'
-
- if form.getField('rows'):
- self.rows = int(form.getField('rows').getValues()[0])
- else:
- self.rows = 3
-
- if form.getField('cols'):
- self.cols = int(form.getField('cols').getValues()[0])
- else:
- self.cols = 3
-
- # Number in a row needed to win
- if form.getField('strike'):
- self.strike = int(form.getField('strike').getValues()[0])
- else:
- self.strike = 3
-
- # Received an invitation
- def invited(self, msg):
- self.read_invitation(msg)
-
- # The number of the move about to be made
- self.next_move_id = 1
-
- # Display the board
- self.board = TicTacToeBoard(self, self.rows, self.cols)
-
- # Accept the invitation, join the game
- response = nbxmpp.Message()
-
- join = response.NT.join
- join.setNamespace(NS_GAMES)
-
- self.send(response)
-
- if self.role_o == 'x':
- self.role_s = 'o'
-
- self.their_turn()
- else:
- self.role_s = 'x'
- self.role_o = 'o'
-
- self.our_turn()
-
- # Just sent an invitation, expecting a reply
- def wait_for_invite_response(self, msg):
- if msg.getTag('join', namespace=NS_GAMES):
- self.board = TicTacToeBoard(self, self.rows, self.cols)
-
- if self.role_s == 'x':
- self.our_turn()
- else:
- self.their_turn()
-
- elif msg.getTag('decline', namespace=NS_GAMES):
- app.nec.push_incoming_event(
- InformationEvent(
- None,
- conn=self.conn,
- level='info',
- pri_txt=_('Invitation Declined'),
- sec_txt=_('%(name)s declined your invitation to play Tic '
- 'Tac Toe.') % {'name': self.name}))
- self.conn.delete_session(str(self.jid), self.thread_id)
-
- def decline_invitation(self):
- msg = nbxmpp.Message()
-
- terminate = msg.NT.decline
- terminate.setNamespace(NS_GAMES)
-
- self.send(msg)
-
- def treat_terminate(self, msg):
- term = msg.getTag('terminate', namespace=NS_GAMES)
- if term:
- if term.getAttr('reason') == 'resign':
- self.board.state = 'resign'
- self.board.win.queue_draw()
- self.received = self.game_over
- return True
-
- # Silently ignores any received messages
- def ignore(self, msg):
- self.treat_terminate(msg)
-
- def game_over(self, msg):
- invite = msg.getTag('invite', namespace=NS_GAMES)
-
- # Ignore messages unless they're renewing the game
- if invite and invite.getAttr('type') == 'renew':
- self.invited(msg)
-
- def wait_for_move(self, msg):
- if self.treat_terminate(msg):
- return
- turn = msg.getTag('turn', namespace=NS_GAMES)
- move = turn.getTag('move', namespace=NS_GAMES_TICTACTOE)
-
- row = int(move.getAttr('row'))
- col = int(move.getAttr('col'))
- id_ = int(move.getAttr('id'))
-
- if id_ != self.next_move_id:
- log.warning('unexpected move id, lost a move somewhere?')
- return
-
- try:
- self.board.mark(row, col, self.role_o)
- except InvalidMove:
- # Received an invalid move, end the game.
- self.board.cheated()
- self.end_game('cheating')
- self.received = self.game_over
- return
-
- # Check win conditions
- if self.board.check_for_strike(self.role_o, row, col, self.strike):
- self.lost()
- elif self.board.full():
- self.drawn()
- else:
- self.next_move_id += 1
-
- self.our_turn()
-
- def is_my_turn(self):
- return self.received == self.ignore
-
- def our_turn(self):
- # Ignore messages until we've made our move
- self.received = self.ignore
- self.board.set_title('your turn')
-
- def their_turn(self):
- self.received = self.wait_for_move
- self.board.set_title('their turn')
-
- # called when the board receives input
- def move(self, row, col):
- try:
- self.board.mark(row, col, self.role_s)
- except InvalidMove:
- log.warning('You made an invalid move')
- return
-
- self.send_move(row, col)
-
- # Check win conditions
- if self.board.check_for_strike(self.role_s, row, col, self.strike):
- self.won()
- elif self.board.full():
- self.drawn()
- else:
- self.next_move_id += 1
-
- self.their_turn()
-
- # Sends a move message
- def send_move(self, row, column):
- msg = nbxmpp.Message()
- msg.setType('chat')
-
- turn = msg.NT.turn
- turn.setNamespace(NS_GAMES)
-
- move = turn.NT.move
- move.setNamespace(NS_GAMES_TICTACTOE)
-
- move.setAttr('row', str(row))
- move.setAttr('col', str(column))
- move.setAttr('id', str(self.next_move_id))
-
- self.send(msg)
-
- # Sends a termination message and ends the game
- def end_game(self, reason):
- msg = nbxmpp.Message()
-
- terminate = msg.NT.terminate
- terminate.setNamespace(NS_GAMES)
- terminate.setAttr('reason', reason)
-
- self.send(msg)
-
- self.received = self.game_over
-
- def won(self):
- self.end_game('won')
- self.board.won()
-
- def lost(self):
- self.end_game('lost')
- self.board.lost()
-
- def drawn(self):
- self.end_game('draw')
- self.board.drawn()
-
-
-class DrawBoard(Gtk.DrawingArea):
- def __init__(self):
- Gtk.DrawingArea.__init__(self)
- self.set_size_request(200, 200)
- self.set_property('expand', True)
-
-
-class TicTacToeBoard:
- def __init__(self, session, rows, cols):
- self.session = session
-
- self.state = 'None'
-
- self.rows = rows
- self.cols = cols
-
- self.board = [[None] * self.cols for r in range(self.rows)]
-
- self.setup_window()
-
- # Check if the last move (at row r and column c) won the game
- def check_for_strike(self, p, r, c, strike):
- # Number in a row: up and down, left and right
- tallyI = 0
- tally_ = 0
-
- # Number in a row: diagonal
- # (imagine L or F as two sides of a right triangle: L\ or F/)
- tallyL = 0
- tallyF = 0
-
- # Convert real columns to internal columns
- r -= 1
- c -= 1
-
- for d in range(-strike, strike):
- r_in_range = 0 <= r+d < self.rows
- c_in_range = 0 <= c+d < self.cols
-
- # Vertical check
- if r_in_range:
- tallyI = tallyI + 1
- if self.board[r+d][c] != p:
- tallyI = 0
-
- # Horizontal check
- if c_in_range:
- tally_ = tally_ + 1
- if self.board[r][c+d] != p:
- tally_ = 0
-
- # Diagonal checks
- if r_in_range and c_in_range:
- tallyL = tallyL + 1
- if self.board[r+d][c+d] != p:
- tallyL = 0
-
- if r_in_range and 0 <= c-d < self.cols:
- tallyF = tallyF + 1
- if self.board[r+d][c-d] != p:
- tallyF = 0
-
- if any([t == strike for t in (tallyL, tallyF, tallyI, tally_)]):
- return True
-
- return False
-
- # Is the board full?
- def full(self):
- for r in range(self.rows):
- for c in range(self.cols):
- if self.board[r][c] is None:
- return False
-
- return True
-
- def setup_window(self):
- self.win = Gtk.Window()
- draw = DrawBoard()
- self.win.add(draw)
-
- self.title_prefix = _('Tic Tac Toe with %s') % self.session.name
- self.set_title()
-
- self.win.add_events(Gdk.EventMask.BUTTON_PRESS_MASK)
- self.win.connect('button-press-event', self.clicked)
-
- draw.connect('draw', self.do_draw)
-
- self.win.show_all()
-
- def clicked(self, widget, event):
- if not self.session.is_my_turn():
- return
-
- (width, height) = widget.get_size()
-
- # Convert click co-ordinates to row and column
- row_height = height // self.rows
- col_width = width // self.cols
-
- row = int(event.y // row_height) + 1
- column = int(event.x // col_width) + 1
-
- self.session.move(row, column)
-
- # This actually draws the board
- def do_draw(self, _widget, cr):
- cr.set_source_rgb(1.0, 1.0, 1.0)
-
- layout = PangoCairo.create_layout(cr)
- text_height = layout.get_pixel_extents()[1].height
-
- (width, height) = self.win.get_size()
-
- row_height = (height - text_height) // self.rows
- col_width = width // self.cols
-
- cr.set_source_rgb(0, 0, 0)
- cr.set_line_width(2)
- for x in range(1, self.cols):
- cr.move_to(col_width * x, 0)
- cr.line_to(col_width * x, height - text_height)
- for x in range(1, self.rows):
- cr.move_to(0, row_height * x)
- cr.line_to(width, row_height * x)
- cr.stroke()
-
- cr.move_to(0, height - text_height)
- if self.state == 'None':
- if self.session.is_my_turn():
- txt = _('It’s your turn')
- else:
- txt = _('It’s %(name)s\'s turn') % {'name': self.session.name}
- elif self.state == 'won':
- txt = _('You won!')
- elif self.state == 'lost':
- txt = _('You lost!')
- elif self.state == 'resign': # Other part resigned
- txt = _('%(name)s capitulated') % {'name': self.session.name}
- elif self.state == 'cheated': # Other part cheated
- txt = _('%(name)s cheated') % {'name': self.session.name}
- else: # Draw
- txt = _('It’s a draw')
- layout.set_text(txt, -1)
- # Inform Pango to re-layout the text with the new transformation
- PangoCairo.update_layout(cr, layout)
- PangoCairo.show_layout(cr, layout)
-
- for i in range(self.rows):
- for j in range(self.cols):
- if self.board[i][j] == 'x':
- self.draw_x(cr, i, j, row_height, col_width)
- elif self.board[i][j] == 'o':
- self.draw_o(cr, i, j, row_height, col_width)
-
- def draw_x(self, cr, row, col, row_height, col_width):
- if self.session.role_s == 'x':
- color = '#3d79fb' # Out
- else:
- color = '#f03838' # Red
- rgba = Gdk.RGBA()
- rgba.parse(color)
- cr.set_source_rgba(rgba.red, rgba.green, rgba.blue, rgba.alpha)
-
- top = row_height * (row + 0.2)
- bottom = row_height * (row + 0.8)
-
- left = col_width * (col + 0.2)
- right = col_width * (col + 0.8)
-
- cr.set_line_width(row_height / 5)
-
- cr.move_to(left, top)
- cr.line_to(right, bottom)
-
- cr.move_to(right, top)
- cr.line_to(left, bottom)
-
- cr.stroke()
-
- def draw_o(self, cr, row, col, row_height, col_width):
- if self.session.role_s == 'o':
- color = '#3d79fb' # out
- else:
- color = '#f03838' # red
- rgba = Gdk.RGBA()
- rgba.parse(color)
- cr.set_source_rgba(rgba.red, rgba.green, rgba.blue, rgba.alpha)
-
- x = col_width * (col + 0.5)
- y = row_height * (row + 0.5)
-
- cr.arc(x, y, row_height/4, 0, 2.0*3.2) # Slightly further than 2*pi
-
- cr.set_line_width(row_height / 5)
- cr.stroke()
-
- # Mark a move on the board
- def mark(self, row, column, player):
- if self.board[row-1][column-1]:
- raise InvalidMove
- self.board[row-1][column-1] = player
-
- self.win.queue_draw()
-
- def set_title(self, suffix=None):
- str_ = self.title_prefix
-
- if suffix:
- str_ += ': ' + suffix
-
- self.win.set_title(str_)
-
- def won(self):
- self.state = 'won'
- self.set_title(_('You won!'))
- self.win.queue_draw()
-
- def lost(self):
- self.state = 'lost'
- self.set_title(_('You’ve lost.'))
- self.win.queue_draw()
-
- def drawn(self):
- self.state = 'drawn'
- self.win.set_title(_('%s: it’s a draw.') % self.title_prefix)
- self.win.queue_draw()
-
- def cheated(self):
- self.state == 'cheated'
- self.win.queue_draw()
diff --git a/tictactoe/tictactoe.png b/tictactoe/tictactoe.png
deleted file mode 100644
index e91fd3f..0000000
Binary files a/tictactoe/tictactoe.png and /dev/null differ