add game report

This commit is contained in:
JerryXiao 2018-12-30 15:24:45 +08:00
parent 986300d9fe
commit e15252bca4
Signed by: Jerry
GPG key ID: 9D9CE43650FF2BAA
2 changed files with 98 additions and 52 deletions

View file

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import numpy as np import numpy as np
from random import randint from random import randint
from copy import deepcopy
# 0 - 8: means 0-8 mines, not opened # 0 - 8: means 0-8 mines, not opened
# opened block = the value of not opened block + 10 # opened block = the value of not opened block + 10
@ -42,6 +43,7 @@ class Board():
self.width = width self.width = width
self.mines = mines self.mines = mines
self.map = None self.map = None
self.mmap = None
self.moves = list() self.moves = list()
self.state = 0 # 0:not playing, 1:playing, 2:win, 3:dead self.state = 0 # 0:not playing, 1:playing, 2:win, 3:dead
def __gen_map(self, first_move): def __gen_map(self, first_move):
@ -72,6 +74,7 @@ class Board():
if nbr_value == IS_MINE: if nbr_value == IS_MINE:
mine_count += 1 mine_count += 1
self.map[row][col] = mine_count self.map[row][col] = mine_count
self.mmap = deepcopy(self.map)
def __iter_neighbour(self, row, col, return_rc=True): def __iter_neighbour(self, row, col, return_rc=True):
height = self.height height = self.height
width = self.width width = self.width

View file

@ -4,7 +4,9 @@ from mscore import Board, check_params
from copy import deepcopy from copy import deepcopy
from telegram import InlineKeyboardMarkup, InlineKeyboardButton from telegram import InlineKeyboardMarkup, InlineKeyboardButton
from telegram.ext import Updater, CommandHandler, CallbackQueryHandler from telegram.ext import Updater, CommandHandler, CallbackQueryHandler
from telegram.error import TimedOut as TimedOutError
from numpy import array_equal from numpy import array_equal
import time
import logging import logging
logging.basicConfig(level=logging.INFO,format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') logging.basicConfig(level=logging.INFO,format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
@ -21,6 +23,17 @@ UNOPENED_CELL = "\u2588"
FLAGGED_CELL = "\u259a" FLAGGED_CELL = "\u259a"
STEPPED_CELL = "*" STEPPED_CELL = "*"
WIN_TEXT_TEMPLATE = "哇所有奇怪的地方都被你打开啦…好羞羞\n" \
"地图Op {s_op} / Is {s_is} / 3bv {s_3bv}\n操作总数 {ops_count}\n" \
"统计:\n{ops_list}\n{last_player} 你要对人家负责哟/// ///\n\n" \
"用时{time}秒,超时{timeouts}\n\n" \
"/mine@{bot_username} 开始新游戏"
LOSE_TEXT_TEMPLATE = "一道火光之后,你就在天上飞了呢…好奇怪喵\n" \
"地图Op {s_op} / Is {s_is} / 3bv {s_3bv}\n操作总数 {ops_count}\n" \
"统计:\n{ops_list}\n{last_player} 是我们中出的叛徒!\n\n" \
"用时{time}秒,超时{timeouts}\n\n" \
"/mine@{bot_username} 开始新游戏"
def display_username(user, atuser=True, shorten=False, markdown=True): def display_username(user, atuser=True, shorten=False, markdown=True):
""" """
@ -40,43 +53,50 @@ def display_username(user, atuser=True, shorten=False, markdown=True):
return name return name
class Game(): class Game():
def __init__(self, board, board_hash, group, creators): def __init__(self, board, group, creator):
self.board = board self.board = board
self.board_hash = board_hash
self.group = group self.group = group
self.creators = creators self.creator = creator
self.actions = dict() self.actions = dict()
self.last_player = None
self.start_time = time.time()
self.extra = {"timeout": 0}
def save_action(self, user, spot): def save_action(self, user, spot):
'''spot is supposed to be a tuple''' '''spot is supposed to be a tuple'''
self.last_player = user
if self.actions.get(user, None): if self.actions.get(user, None):
self.actions[user].append(spot) self.actions[user].append(spot)
else: else:
self.actions[user] = [spot,] self.actions[user] = [spot,]
def actions_sum(self):
mysum = 0
for user in self.actions:
count = len(self.actions.get(user, list()))
mysum += count
return mysum
def get_last_player(self):
return display_username(self.last_player)
def get_actions(self): def get_actions(self):
'''Convert actions into text''' '''Convert actions into text'''
msg = "" msg = ""
for user in self.actions: for user in self.actions:
count = len(self.actions.get(user, list())) count = len(self.actions.get(user, list()))
msg = "{}{}: {}项操作\n".format(msg, display_username(user), count) msg = "{}{} - {}项操作\n".format(msg, display_username(user), count)
return msg return msg
class GameManager: class GameManager:
__games = list() __games = dict()
def append(self, board, board_hash, group_id, creator_id): def append(self, board, board_hash, group_id, creator_id):
self.__games.append(Game(board, board_hash, group_id, creator_id)) self.__games[board_hash] = Game(board, group_id, creator_id)
def remove(self, board_hash): def remove(self, board_hash):
board = self.get_game_from_hash(board_hash) board = self.get_game_from_hash(board_hash)
if board: if board:
self.__games.remove(board) del self.__games[board_hash]
return True return True
else: else:
return False return False
def get_game_from_hash(self, board_hash): def get_game_from_hash(self, board_hash):
for gm in self.__games: return self.__games.get(board_hash, None)
if gm.board_hash == board_hash:
return gm
else:
return None
def count(self): def count(self):
return len(self.__games) return len(self.__games)
@ -135,35 +155,8 @@ def send_status(bot, update):
count = game_manager.count() count = game_manager.count()
update.message.reply_text('当前进行的游戏: {}'.format(count)) update.message.reply_text('当前进行的游戏: {}'.format(count))
def gen_keyboard(board): def update_keyboard(bot, bhash, game, chat_id, message_id):
pass def gen_keyboard(board):
def handle_button_click(bot, update):
msg = update.callback_query.message
user = update.callback_query.from_user
chat_id = update.callback_query.message.chat.id
data = update.callback_query.data
logger.debug('Button clicked by {}, data={}.'.format(user.id, data))
bot.answer_callback_query(callback_query_id=update.callback_query.id)
try:
data = data.split(' ')
data = [int(i) for i in data]
(bhash, row, col) = data
except Exception as err:
logger.info('Unknown callback data: {} from user {}'.format(data, user.id))
return
game = game_manager.get_game_from_hash(bhash)
if game is None:
logger.info("No game found for hash {}".format(bhash))
return
board = game.board
FIRST_MOVE = False
if board.state == 0:
FIRST_MOVE = True
else:
mmap = deepcopy(board.map)
board.move((row, col))
if FIRST_MOVE or (not array_equal(board.map, mmap)) or board.state == 2:
keyboard = list() keyboard = list()
for row in range(board.height): for row in range(board.height):
current_row = list() current_row = list()
@ -181,18 +174,68 @@ def handle_button_click(bot, update):
cell = InlineKeyboardButton(text=cell_text, callback_data="{} {} {}".format(bhash, row, col)) cell = InlineKeyboardButton(text=cell_text, callback_data="{} {} {}".format(bhash, row, col))
current_row.append(cell) current_row.append(cell)
keyboard.append(current_row) keyboard.append(current_row)
if board.state != 1: return keyboard
if board.state == 2: keyboard = gen_keyboard(game.board)
reply_text = "Win" try:
game_manager.remove(bhash) bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id,
elif board.state == 3: reply_markup=InlineKeyboardMarkup(keyboard))
reply_text = "Lose" except TimedOutError:
game_manager.remove(bhash) logger.debug('time out in game {}.'.format(bhash))
game.extra["timeout"] += 1
def handle_button_click(bot, update):
msg = update.callback_query.message
user = update.callback_query.from_user
chat_id = update.callback_query.message.chat.id
data = update.callback_query.data
logger.debug('Button clicked by {}, data={}.'.format(user.id, data))
bot.answer_callback_query(callback_query_id=update.callback_query.id)
try:
data = data.split(' ')
data = [int(i) for i in data]
(bhash, row, col) = data
except Exception as err:
logger.info('Unknown callback data: {} from user {}'.format(data, user.id))
return
game = game_manager.get_game_from_hash(bhash)
if game is None:
logger.debug("No game found for hash {}".format(bhash))
return
board = game.board
if board.state == 0:
mmap = None
board.move((row, col))
game.save_action(user, (row, col))
update_keyboard(bot, bhash, game, chat_id, msg.message_id)
else:
mmap = deepcopy(board.map)
board.move((row, col))
if board.state != 1:
# if this is the first move, there's no mmap
if mmap is not None:
game.save_action(user, (row, col))
update_keyboard(bot, bhash, game, chat_id, msg.message_id)
ops_count = game.actions_sum()
ops_list = game.get_actions()
last_player = game.get_last_player()
bot_username = bot.username
time_used = time.time() - game.start_time
timeouts = game.extra["timeout"]
if board.state == 2:
template = WIN_TEXT_TEMPLATE
else: else:
reply_text = msg.text_markdown template = LOSE_TEXT_TEMPLATE
bot.edit_message_text(chat_id=chat_id, message_id=msg.message_id, myreply = template.format(s_op=0, s_is=0, s_3bv=0, ops_count=ops_count,
text=reply_text, parse_mode="Markdown", ops_list=ops_list, last_player=last_player,
reply_markup=InlineKeyboardMarkup(keyboard)) time=round(time_used, 4), timeouts=timeouts,
bot_username=bot_username)
msg.reply_text(myreply, parse_mode="Markdown")
game_manager.remove(bhash)
else:
if mmap is not None and (not array_equal(board.map, mmap)):
game.save_action(user, (row, col))
update_keyboard(bot, bhash, game, chat_id, msg.message_id)
updater.dispatcher.add_handler(CommandHandler('start', send_help)) updater.dispatcher.add_handler(CommandHandler('start', send_help))