moved to subfolder
This commit is contained in:
@@ -1,27 +0,0 @@
|
||||
About
|
||||
-----
|
||||
Komodo SudokuCC GUI
|
||||
|
||||
Just solve Sudoku and earn SUDOKU coins!
|
||||
|
||||

|
||||
|
||||
To run you need up and running SUDOKU chain daemon built from latest https://github.com/jl777/komodo/tree/FSM and started with valid for your wallet pubkey in `-pubkey=` param.
|
||||
|
||||
SUDOKU chain params:
|
||||
```./komodod -ac_name=SUDOKU -ac_supply=1000000 -pubkey=<yourpubkey> -addnode=5.9.102.210 -gen -genproclimit=1 -ac_cclib=sudoku -ac_perc=10000000 -ac_reward=100000000 -ac_cc=60000 -ac_script=2ea22c80203d1579313abe7d8ea85f48c65ea66fc512c878c0d0e6f6d54036669de940febf8103120c008203000401cc &```
|
||||
|
||||
1) install dependencies:
|
||||
|
||||
```
|
||||
$ sudo apt-get install python-pygame libgnutls28-dev
|
||||
$ pip install requests wheel slick-bitcoinrpc pygame
|
||||
```
|
||||
|
||||
2) and then start:
|
||||
|
||||
```
|
||||
$ git clone https://github.com/tonymorony/Komodoku
|
||||
$ cd Komodoku
|
||||
$ python Sudoku.py
|
||||
```
|
||||
Binary file not shown.
@@ -1,362 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright (C) 2010 Paul Bourke <pauldbourke@gmail.com>
|
||||
# Copyright (C) 2019 Anton Lysakov <tlysakov@gmail.com>
|
||||
#
|
||||
# This program 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.
|
||||
#
|
||||
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import pygame
|
||||
import sys
|
||||
import random
|
||||
import sudoku_kmdlib
|
||||
import time
|
||||
|
||||
class PyGameBoard():
|
||||
"""Represents the game's frontend using pygame"""
|
||||
|
||||
def __init__(self, engine, windowSize, gridValues, timestampValues):
|
||||
pygame.init()
|
||||
pygame.display.set_caption('Sudoku')
|
||||
self.__engine = engine
|
||||
self.__gridValues = gridValues
|
||||
self.__timestampValues = timestampValues
|
||||
self.__screen = pygame.display.set_mode(windowSize)
|
||||
background = pygame.image.load(sys.path[0] + '/background.png').convert()
|
||||
board = pygame.image.load(sys.path[0] + '/board.png')
|
||||
boardX = boardY = 10
|
||||
self.__screen.blit(background, (0, 0))
|
||||
self.__screen.blit(board, (boardX, boardY))
|
||||
self.__tiles = self.__createTiles(boardX, boardY)
|
||||
self.__drawUI()
|
||||
self.__draw()
|
||||
|
||||
def __draw(self):
|
||||
"""Handles events and updates display buffer"""
|
||||
while True:
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
sys.exit()
|
||||
elif event.type == pygame.MOUSEBUTTONUP and event.button == 1:
|
||||
self.__handleMouse(event.pos)
|
||||
elif (event.type == pygame.KEYUP):
|
||||
self.__handleKeyboard(event.key)
|
||||
pygame.display.flip()
|
||||
|
||||
def __drawUI(self):
|
||||
'''Draws the text buttons along the right panel'''
|
||||
font = pygame.font.Font(sys.path[0] + '/Roboto-Light.ttf', 28)
|
||||
font.set_underline(True)
|
||||
self.__titleText = font.render('Sudoku', 1, (0, 0, 0))
|
||||
self.__titleTextRect = self.__titleText.get_rect()
|
||||
self.__titleTextRect.centerx = 445
|
||||
self.__titleTextRect.centery = 30
|
||||
self.__screen.blit(self.__titleText, self.__titleTextRect)
|
||||
|
||||
font = pygame.font.Font(sys.path[0] + '/Roboto-Light.ttf', 14)
|
||||
self.__titleText = font.render('TonyL 2019', 1, (0, 0, 0))
|
||||
self.__titleTextRect = self.__titleText.get_rect()
|
||||
self.__titleTextRect.centerx = 445
|
||||
self.__titleTextRect.centery = 55
|
||||
self.__screen.blit(self.__titleText, self.__titleTextRect)
|
||||
|
||||
font = pygame.font.Font(sys.path[0] + '/Roboto-Light.ttf', 24)
|
||||
self.__newGameText = font.render('-New Game-', 1, (0, 0, 0))
|
||||
self.__newGameTextRect = self.__newGameText.get_rect()
|
||||
self.__newGameTextRect.centerx = 495
|
||||
self.__newGameTextRect.centery = 180
|
||||
self.__screen.blit(self.__newGameText, self.__newGameTextRect)
|
||||
|
||||
self.__solveText = font.render('-Check Balance-', 1, (0, 0, 0))
|
||||
self.__solveTextRect = self.__solveText.get_rect()
|
||||
self.__solveTextRect.centerx = 495
|
||||
self.__solveTextRect.centery = 220
|
||||
self.__screen.blit(self.__solveText, self.__solveTextRect)
|
||||
|
||||
font = pygame.font.Font(sys.path[0] + '/Roboto-Light.ttf', 24)
|
||||
self.__checkText = font.render('-Check Solution-', 1, (0, 0, 0))
|
||||
self.__checkTextRect = self.__checkText.get_rect()
|
||||
self.__checkTextRect.centerx = 495
|
||||
self.__checkTextRect.centery = 260
|
||||
self.__screen.blit(self.__checkText, self.__checkTextRect)
|
||||
|
||||
def __handleKeyboard(self, key):
|
||||
"""Get key pressed and update the game board"""
|
||||
validKeys = {pygame.K_0: "0", pygame.K_1: "1", pygame.K_2: "2",
|
||||
pygame.K_3: "3", pygame.K_4: "4", pygame.K_5: "5",
|
||||
pygame.K_6: "6", pygame.K_7: "7", pygame.K_8: "8",
|
||||
pygame.K_9: "9", pygame.K_BACKSPACE: "", pygame.K_DELETE: ""}
|
||||
if key == pygame.K_ESCAPE:
|
||||
sys.exit()
|
||||
elif key in validKeys:
|
||||
i = self.__currentTile.getGridLoc()[0]
|
||||
j = self.__currentTile.getGridLoc()[1]
|
||||
cell_num = 9 * i + (j + 1)
|
||||
self.__currentTile.setFontColor(pygame.color.THECOLORS['blue'])
|
||||
self.__currentTile.updateValue(validKeys[key])
|
||||
self.__gridValues[i][j] = self.__currentTile.getValue()
|
||||
self.__timestampValues[cell_num] = int(round(time.time()))
|
||||
|
||||
def __handleMouse(self, (x, y)):
|
||||
for row in self.__tiles:
|
||||
for tile in row:
|
||||
if tile.getRect().collidepoint(x, y):
|
||||
if not tile.isReadOnly():
|
||||
tile.highlight(pygame.color.THECOLORS['lightyellow'])
|
||||
if self.__currentTile.isCorrect():
|
||||
self.__currentTile.unhighlight()
|
||||
else:
|
||||
self.__currentTile.highlight((255, 164, 164))
|
||||
self.__currentTile = tile
|
||||
if self.__newGameTextRect.collidepoint(x, y):
|
||||
self.__engine.startNewGame()
|
||||
elif self.__solveTextRect.collidepoint(x, y):
|
||||
self.__engine.getSolution()
|
||||
elif self.__checkTextRect.collidepoint(x, y):
|
||||
ret = self.__engine.checkSolution(self.__gridValues, self.__timestampValues)
|
||||
|
||||
def __updateBoard(self, gridValues):
|
||||
for i in range(9):
|
||||
for j in range(9):
|
||||
self.__tiles[i][j].updateValue(gridValues[i][j])
|
||||
|
||||
def __unhightlightBoard(self):
|
||||
for i in range(9):
|
||||
for j in range(9):
|
||||
self.__tiles[i][j].unhighlight()
|
||||
|
||||
def __createTiles(self, initX=0, initY=0):
|
||||
"""Set up a list of tiles corresponding to the grid, along with
|
||||
each ones location coordinates on the board"""
|
||||
square_size = 40
|
||||
tiles = list()
|
||||
x = y = 0
|
||||
for i in range(0, 9):
|
||||
row = list()
|
||||
for j in range(0, 9):
|
||||
if j in (0, 1, 2):
|
||||
x = (j * 41) + (initX + 2)
|
||||
if j in (3, 4, 5):
|
||||
x = (j * 41) + (initX + 6)
|
||||
if j in (6, 7, 8):
|
||||
x = (j * 41) + (initX + 10)
|
||||
if i in (0, 1, 2):
|
||||
y = (i * 41) + (initY + 2)
|
||||
if i in (3, 4, 5):
|
||||
y = (i * 41) + (initY + 6)
|
||||
if i in (6, 7, 8):
|
||||
y = (i * 41) + (initY + 10)
|
||||
tile = Tile(self.__gridValues[i][j], (x, y), (i, j), square_size)
|
||||
row.append(tile)
|
||||
tiles.append(row)
|
||||
self.__currentTile = tiles[0][0]
|
||||
return tiles
|
||||
|
||||
|
||||
class Tile():
|
||||
"""Represents a graphical tile on the board"""
|
||||
|
||||
def __init__(self, value, coords, gridLoc, size):
|
||||
xpos = coords[0]
|
||||
ypos = coords[1]
|
||||
self.__fontColor = pygame.color.THECOLORS["black"]
|
||||
self.__readOnly = False
|
||||
self.__colorSquare = pygame.Surface((size, size)).convert()
|
||||
self.__colorSquare.fill(pygame.color.THECOLORS['white'], None, pygame.BLEND_RGB_ADD)
|
||||
self.__colorSquareRect = self.__colorSquare.get_rect()
|
||||
self.__colorSquareRect = self.__colorSquareRect.move(xpos + 1, ypos + 1)
|
||||
self.__value = value
|
||||
self.__gridLoc = gridLoc
|
||||
self.__screen = pygame.display.get_surface()
|
||||
self.__rect = pygame.Rect(xpos, ypos, size, size)
|
||||
self.__isCorrect = True
|
||||
if self.__value is not '-':
|
||||
self.__readOnly = True
|
||||
self.__draw()
|
||||
|
||||
def updateValue(self, value):
|
||||
self.__value = value
|
||||
self.__draw()
|
||||
|
||||
def isCorrect(self):
|
||||
return self.__isCorrect
|
||||
|
||||
def setCorrect(self, isCorrect):
|
||||
self.__isCorrect = isCorrect
|
||||
|
||||
def setFontColor(self, fontColor):
|
||||
self.__fontColor = fontColor
|
||||
|
||||
def getValue(self):
|
||||
return self.__value
|
||||
|
||||
def getRect(self):
|
||||
return self.__rect
|
||||
|
||||
def getGridLoc(self):
|
||||
return self.__gridLoc
|
||||
|
||||
def isReadOnly(self):
|
||||
return self.__readOnly
|
||||
|
||||
def highlight(self, color):
|
||||
if self.__readOnly is True:
|
||||
return
|
||||
self.__colorSquare.fill(color)
|
||||
self.__draw()
|
||||
|
||||
def unhighlight(self):
|
||||
self.__colorSquare.fill((255, 225, 255), None, pygame.BLEND_RGB_ADD)
|
||||
self.__draw()
|
||||
|
||||
def __draw(self):
|
||||
value = self.__value
|
||||
if self.__value == '-':
|
||||
value = ''
|
||||
font = pygame.font.Font(sys.path[0] + '/Roboto-Light.ttf', 24)
|
||||
text = font.render(str(value), 1, self.__fontColor)
|
||||
textpos = text.get_rect()
|
||||
textpos.centerx = self.__rect.centerx
|
||||
textpos.centery = self.__rect.centery
|
||||
self.__screen.blit(self.__colorSquare, self.__colorSquareRect)
|
||||
self.__screen.blit(text, textpos)
|
||||
|
||||
|
||||
class Sudoku:
|
||||
"""Represents the game's backend and logic"""
|
||||
|
||||
def __init__(self, puzzleFile, rpc_connection):
|
||||
self.__puzzleFile = puzzleFile
|
||||
self.__rpc_connection = rpc_connection
|
||||
self.startNewGame()
|
||||
|
||||
def startNewGame(self):
|
||||
self.__linePuzzle = self.__loadPuzzle(self.__puzzleFile)
|
||||
gridValues = self.lineToGrid(self.__linePuzzle)
|
||||
# prefill 0 timestamps for already known numbers
|
||||
timestampValues = self.prefill_timestamps(gridValues)
|
||||
board = PyGameBoard(self, (600, 400), gridValues, timestampValues)
|
||||
board.setValues(gridValues)
|
||||
|
||||
def __loadPuzzle(self, listName):
|
||||
self.__chosen_puzzle = random.choice(listName)
|
||||
puzzle = self.__rpc_connection.cclib("txidinfo", "17", '"%22' + self.__chosen_puzzle + '%22"')["unsolved"]
|
||||
print "Puzzle ID: " + self.__chosen_puzzle
|
||||
print "Reward amount: " + str(self.__rpc_connection.cclib("txidinfo", "17", '"%22' + self.__chosen_puzzle + '%22"')["amount"])
|
||||
ret = []
|
||||
linePuzzle = str(puzzle)
|
||||
for i in linePuzzle:
|
||||
ret.append(i)
|
||||
return ret
|
||||
|
||||
def gridToLine(self, grid):
|
||||
linePuzzle = ''
|
||||
for i in range(9):
|
||||
for j in range(9):
|
||||
linePuzzle += grid[i][j]
|
||||
return linePuzzle
|
||||
|
||||
def lineToGrid(self, linePuzzle):
|
||||
assert (len(linePuzzle) == 81)
|
||||
grid = []
|
||||
for i in xrange(0, 81, 9):
|
||||
grid.append(linePuzzle[i:i + 9])
|
||||
return grid
|
||||
|
||||
def getSolution(self):
|
||||
balance = self.__rpc_connection.cclibaddress("17")["mybalance"]
|
||||
print "Your balance: " + str(balance)
|
||||
|
||||
def __solve(self, linePuzzle):
|
||||
linePuzzle = ''.join(linePuzzle)
|
||||
i = linePuzzle.find('-')
|
||||
if i == -1:
|
||||
return linePuzzle
|
||||
|
||||
excluded_numbers = set()
|
||||
for j in range(81):
|
||||
if self.sameRow(i, j) or self.sameCol(i, j) or self.sameBlock(i, j):
|
||||
excluded_numbers.add(linePuzzle[j])
|
||||
|
||||
for m in '123456789':
|
||||
if m not in excluded_numbers:
|
||||
funcRet = self.__solve(linePuzzle[:i] + m + linePuzzle[i + 1:])
|
||||
if funcRet is not None:
|
||||
return funcRet
|
||||
|
||||
def prefill_timestamps(self, grid):
|
||||
timestamps = {}
|
||||
for i in range(9):
|
||||
for j in range(9):
|
||||
if grid[i][j] != '-':
|
||||
cell_num = 9 * i + ( j + 1 )
|
||||
timestamps[cell_num] = 0
|
||||
return timestamps
|
||||
|
||||
def sameRow(self, i, j):
|
||||
return (i / 9 == j / 9)
|
||||
|
||||
def sameCol(self, i, j):
|
||||
return (i - j) % 9 == 0
|
||||
|
||||
def sameBlock(self, i, j):
|
||||
return (i / 27 == j / 27 and i % 9 / 3 == j % 9 / 3)
|
||||
|
||||
def checkSolution(self, attemptGrid, timestampValues):
|
||||
# [%22<txid>%22,%22<solution>%22,t0,t1,t2,...]
|
||||
attemptLine = self.gridToLine(attemptGrid)
|
||||
|
||||
#print attemptLine
|
||||
#print timestampValues
|
||||
timestampsline = ""
|
||||
for timestamp in timestampValues.values():
|
||||
timestampsline += ","
|
||||
timestampsline += str(timestamp)
|
||||
arg_line = "[%22"+self.__chosen_puzzle+"%22,%22"+attemptLine+"%22"+timestampsline+"]"
|
||||
print arg_line
|
||||
try:
|
||||
solution_info = self.__rpc_connection.cclib("solution", "17", '"' + arg_line + '"')
|
||||
print solution_info
|
||||
solution_txid = self.__rpc_connection.sendrawtransaction(solution_info["hex"])
|
||||
print "Solution accepted!"
|
||||
print solution_txid
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print(solution_info)
|
||||
solution_txid = 'error'
|
||||
return solution_txid
|
||||
|
||||
def main():
|
||||
while True:
|
||||
# Assetchain hardcoded here
|
||||
chain = 'SUDOKU'
|
||||
try:
|
||||
print 'Welcome to the Komodo SudokuCC'
|
||||
rpc_connection = sudoku_kmdlib.def_credentials(chain)
|
||||
pending_puzzles = rpc_connection.cclib("pending", "17")["pending"]
|
||||
puzzle_list = []
|
||||
for puzzle in pending_puzzles:
|
||||
puzzle_list.append(puzzle["txid"])
|
||||
|
||||
except Exception as e:
|
||||
#print rpc_connection
|
||||
print e
|
||||
print 'Cant connect to SUDOKU Daemon! Please re-check if it up'
|
||||
sys.exit()
|
||||
else:
|
||||
print 'Succesfully connected!\n'
|
||||
break
|
||||
newGame = Sudoku(puzzle_list, rpc_connection)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 301 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 5.5 KiB |
@@ -1,41 +0,0 @@
|
||||
import platform
|
||||
import os
|
||||
import re
|
||||
import random
|
||||
from slickrpc import Proxy
|
||||
|
||||
|
||||
# define function that fetchs rpc creds from .conf
|
||||
def def_credentials(chain):
|
||||
rpcport ='';
|
||||
operating_system = platform.system()
|
||||
if operating_system == 'Darwin':
|
||||
ac_dir = os.environ['HOME'] + '/Library/Application Support/Komodo'
|
||||
elif operating_system == 'Linux':
|
||||
ac_dir = os.environ['HOME'] + '/.komodo'
|
||||
elif operating_system == 'Windows':
|
||||
ac_dir = '%s/komodo/' % os.environ['APPDATA']
|
||||
if chain == 'KMD':
|
||||
coin_config_file = str(ac_dir + '/komodo.conf')
|
||||
else:
|
||||
coin_config_file = str(ac_dir + '/' + chain + '/' + chain + '.conf')
|
||||
with open(coin_config_file, 'r') as f:
|
||||
for line in f:
|
||||
l = line.rstrip()
|
||||
if re.search('rpcuser', l):
|
||||
rpcuser = l.replace('rpcuser=', '')
|
||||
elif re.search('rpcpassword', l):
|
||||
rpcpassword = l.replace('rpcpassword=', '')
|
||||
elif re.search('rpcport', l):
|
||||
rpcport = l.replace('rpcport=', '')
|
||||
if len(rpcport) == 0:
|
||||
if chain == 'KMD':
|
||||
rpcport = 7771
|
||||
else:
|
||||
print("rpcport not in conf file, exiting")
|
||||
print("check "+coin_config_file)
|
||||
exit(1)
|
||||
|
||||
return(Proxy("http://%s:%s@127.0.0.1:%d"%(rpcuser, rpcpassword, int(rpcport))))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user