mirror of
https://gitlab.com/oloturia/damastodon.git
synced 2025-01-04 20:47:15 +01:00
abstracted game from the lobby, half implemented 4connect
This commit is contained in:
parent
97298be316
commit
79986232ed
4 changed files with 139 additions and 78 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -1,5 +1,9 @@
|
|||
TOKEN
|
||||
TOKEN.LOCAL
|
||||
TOKEN.OLD
|
||||
DAMA.SECRET
|
||||
DAMA.SECRET.LOCAL
|
||||
DAMA.SECRET.OLD
|
||||
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
|
|
166
damastodon.py
166
damastodon.py
|
@ -2,6 +2,7 @@
|
|||
|
||||
from mastodon import Mastodon
|
||||
import draughts_engine as dama
|
||||
import four_engine
|
||||
import login
|
||||
import pickle
|
||||
import random
|
||||
|
@ -15,7 +16,10 @@ import logging
|
|||
api_url = sys.argv[1]
|
||||
save_position = "/tmp/"
|
||||
CLEANR = re.compile('<.*?>')
|
||||
botname = "@damastodon "
|
||||
#botname = "@damastodon "
|
||||
botname = "@dama "
|
||||
|
||||
available_games = ("draughts","conn4")
|
||||
|
||||
#board appearence
|
||||
frstrow = "🇻1️⃣ 2️⃣ 3️⃣ 4️⃣ 5️⃣ 6️⃣ 7️⃣ 8️⃣\n"
|
||||
|
@ -27,6 +31,9 @@ black_norm="◾ "
|
|||
black_knight="⚫ "
|
||||
empty="🟦 "
|
||||
|
||||
#conn4
|
||||
conn4row = "🇻1️⃣ 2️⃣ 3️⃣ 4️⃣ 5️⃣ 6️⃣ 7️⃣\n"
|
||||
|
||||
#logging config
|
||||
logging.basicConfig(filename="/tmp/dama.log",level=logging.DEBUG)
|
||||
|
||||
|
@ -34,6 +41,71 @@ def cleanHTML(raw):
|
|||
cleanText = re.sub(CLEANR, '',raw)
|
||||
return cleanText
|
||||
|
||||
def lobby(notification,content,account,extension):
|
||||
try:
|
||||
challenged = notification["status"]["mentions"][1]["acct"] #If there isn't another account cited, then the request is malformed
|
||||
except:
|
||||
mastodon.status_post("Hello @"+account+" \n your request is not valid",visibility="direct")
|
||||
return
|
||||
|
||||
if challenged == account: #The user tried to challenge him/herself
|
||||
mastodon.status_post("Hello @"+account+"\n You can't challenge yourself",visibility="direct")
|
||||
return
|
||||
|
||||
if content.split(" ")[0].lower() == extension: #Challenge someone, check if a savegame is already existing
|
||||
if os.path.exists(save_position+challenged+"."+extension):
|
||||
mastodon.status_post("Hello @"+account+" \n the user you challenged is already playing a match",visibility="direct")
|
||||
return
|
||||
else:
|
||||
with open(save_position+account+"."+extension,"wb") as f: #The request is valid, writes a savegame with the first element as False, that marks that the game isn't started yet
|
||||
pickle.dump("WAIT",f)
|
||||
ident = mastodon.status_post("Hello @"+challenged+" \n@"+account+" challenged you to a match of "+extension+"! Answer \n @"+account+" OK "+extension.upper()+"\n to accept the challenge or \n@"+account+" NO "+extension.upper()+"\n to cancel.",visibility="direct")
|
||||
return
|
||||
elif content.split(" ")[1].lower() == "ok" and content.split(" ")[2].lower() == extension: #The opponent accepted the match
|
||||
try:
|
||||
challenger = notification["status"]["mentions"][1]["acct"]
|
||||
except:
|
||||
mastodon.status_post("Hello @"+account+" \n your request is not valid",visibility="direct") #Somehow, the opponent answered with only one account
|
||||
return
|
||||
try:
|
||||
with open(save_position+challenger+"."+extension,"rb") as f:
|
||||
start = pickle.load(f)
|
||||
except FileNotFoundError:
|
||||
mastodon.status_post("Hello @"+account+" \n unfortunately, your savegame is corrupted or missing",visibility="direct") #The file has moved or corrupted
|
||||
logging.warning("%s file not found",account)
|
||||
return
|
||||
if start != "WAIT":
|
||||
mastodon.status_post("Hello @"+account+" \n your request is not valid",visibility="direct") #The user that challenged us is playing a game with someone else
|
||||
return
|
||||
os.symlink(save_position+challenger+"."+extension,save_position+account+"."+extension) #Linked the two savegames together
|
||||
|
||||
|
||||
if extension == "draughts": #Draughts init
|
||||
board = dama.init_board()
|
||||
mastodon.status_post("◾: @"+account+" ◽: @"+challenger+" \nturn ◽\n"+dama.draw_checkerboard(board,space,white_norm,white_knight,black_norm,black_knight,empty,column,frstrow),visibility="direct")
|
||||
elif extension == "conn4": #Conn4 init
|
||||
board = four_engine.initChequerboard()
|
||||
mastodon.status_post(four_engine.drawChequerboard(board,players=[white_knight,black_knight],space=empty,toprow=conn4row),visibility="direct")
|
||||
with open(save_position+account+"."+extension,"wb") as f:
|
||||
pickle.dump("START",f) #Now the game has started
|
||||
pickle.dump("@"+account,f)
|
||||
pickle.dump("@"+challenger,f)
|
||||
pickle.dump(False,f)
|
||||
pickle.dump(board,f)
|
||||
return
|
||||
elif content.split(" ")[1].lower() == "no" and content.split(" ")[2].lower == extension: #The opponent refused the game
|
||||
try:
|
||||
challenger = notification["status"]["mentions"][1]["acct"]
|
||||
except:
|
||||
mastodon.status_post("Hello @"+account+" \n your request is not valid",visibility="direct") #Only one user in the message
|
||||
return
|
||||
os.remove(save_position+challenger+"."+extension)
|
||||
mastodon.status_post("@"+account+" you cancelled the challenge from @"+challenger,visibility="direct") #Game is cancelled, free to challenge someone else
|
||||
return
|
||||
else:
|
||||
mastodon.status_post("Hello @"+account+" \nI can't understand your command or you're not in a match.\nWrite HELP to see the list of available commands.",visibility="direct") #Every other command for the lobby ends here
|
||||
return
|
||||
|
||||
def check_message(notification):
|
||||
account = notification["account"]["acct"]
|
||||
try:
|
||||
|
@ -41,75 +113,21 @@ def check_message(notification):
|
|||
except KeyError:
|
||||
return
|
||||
content = content[len(botname):]
|
||||
saves = os.listdir(save_position)
|
||||
#saves = os.listdir(save_position)
|
||||
if "help" in content.lower(): #Ask for help
|
||||
mastodon.status_post("Hello @"+account+" \nchallenge an user by writing to me\nCHALL <USERNAME>\nEx. \"CHALL @someone@mastdn.inst.wxyz\"\nThe challenger takes WHITE and begins the match.\nFor movements and jumps, write the coords separated by spaces.\nEx. \"A4 B5\" (normal movement) or \"A4 C6 D8\" (double jump)\nQUIT ends the match.\nCommands are NOT case sensitive.",visibility="direct")
|
||||
mastodon.status_post("Hello @"+account+" \nchallenge an user in a game of draughts by writing to me\nDRAUGHTS <USERNAME>\nEx. \"DRAUGHTS @someone@mastdn.inst.wxyz\"\nThe challenger takes WHITE and begins the match.\nFor movements and jumps, write the coords separated by spaces.\nEx. \"A4 B5\" (normal movement) or \"A4 C6 D8\" (double jump)\nQUIT ends the match.\nCommands are NOT case sensitive.\nTo challenge someone in a game of Connect 4 write CONN4 <USERNAME>.",visibility="direct")
|
||||
return
|
||||
if not os.path.exists(save_position+account): #If there is no a savegame file, then lobby mode is activated
|
||||
try:
|
||||
challenged = notification["status"]["mentions"][1]["acct"] #If there isn't another account cited, then the request is malformed
|
||||
except:
|
||||
mastodon.status_post("Hello @"+account+" \n your request is not valid",visibility="direct")
|
||||
return
|
||||
if content[:5].lower() == "chall": #Challenge someone, check if a savegame is already existing
|
||||
file_save_white = [sv for sv in saves if account in sv]
|
||||
file_save_black = [sv for sv in saves if challenged in sv]
|
||||
if len(file_save_white) > 0: #We are playing a match
|
||||
mastodon.status_post("Hello @"+account+" \n you're already playing a match",visibility="direct")
|
||||
return
|
||||
elif len(file_save_black) > 0: #Our opponent is already playing with someone
|
||||
mastodon.status_post("Hello @"+account+" \n the user you challenged is already playing a match",visibility="direct")
|
||||
return
|
||||
else:
|
||||
with open(save_position+account,"wb") as f: #The request is valid, writes a savegame with the first element as False, that marks that the game isn't started yet
|
||||
pickle.dump("WAIT",f)
|
||||
ident = mastodon.status_post("Hello @"+challenged+" \n@"+account+" challenged you to a match of draughts! Answer \n@"+account+" OK\n to accept the chellenge or \n@"+account+" NO\n to cancel.",visibility="direct")
|
||||
return
|
||||
elif content.split(" ")[1].lower() == "ok": #The opponent accepted the match
|
||||
try:
|
||||
challenger = notification["status"]["mentions"][1]["acct"]
|
||||
except:
|
||||
mastodon.status_post("Hello @"+account+" \n your request is not valid",visibility="direct") #Somehow, the opponent answered with only one account
|
||||
return
|
||||
try:
|
||||
with open(save_position+challenger,"rb") as f:
|
||||
start = pickle.load(f)
|
||||
except FileNotFoundError:
|
||||
mastodon.status_post("Hello @"+account+" \n unfortunately, your savegame is corrupted or missing",visibility="direct") #The file has moved or corrupted
|
||||
logging.warning("%s file not found",account)
|
||||
return
|
||||
if start != "WAIT":
|
||||
mastodon.status_post("Hello @"+account+" \n your request is not valid",visibility="direct") #The user that challenged us is playing a game with someone else
|
||||
return
|
||||
os.symlink(save_position+challenger,save_position+account) #Linked the two savegames together
|
||||
board = dama.init_board()
|
||||
with open(save_position+account,"wb") as f:
|
||||
pickle.dump("START",f) #Now the game has started
|
||||
pickle.dump("@"+account,f)
|
||||
pickle.dump("@"+challenger,f)
|
||||
pickle.dump(False,f)
|
||||
pickle.dump(board,f)
|
||||
mastodon.status_post("◾: @"+account+" ◽: @"+challenger+" \nturn ◽\n"+dama.draw_checkerboard(board,space,white_norm,white_knight,black_norm,black_knight,empty,column,frstrow),visibility="direct")
|
||||
return
|
||||
elif content.split(" ")[1].lower() == "no": #The opponent refused the game
|
||||
try:
|
||||
challenger = notification["status"]["mentions"][1]["acct"]
|
||||
except:
|
||||
mastodon.status_post("Hello @"+account+" \n your request is not valid",visibility="direct") #Only one user in the message
|
||||
return
|
||||
os.remove(save_position+challenger)
|
||||
mastodon.status_post("@"+account+" you cancelled the challenge from @"+challenger,visibility="direct") #Game is cancelled, free to challenge someone else
|
||||
return
|
||||
else:
|
||||
mastodon.status_post("Hello @"+account+" \nI can't understand your command or you're not in a match.\nWrite HELP to see the list of available commands.",visibility="direct") #Every other command for the lobby ends here
|
||||
return
|
||||
else: #We are in a game, so movements are parsed and lobby commands are disabled
|
||||
with open(save_position+account,"rb") as f:
|
||||
|
||||
|
||||
|
||||
#Draughts
|
||||
if os.path.exists(save_position+account+".draughts"): #We are in a game, so movements are parsed and lobby commands are disabled
|
||||
with open(save_position+account+".draughts","rb") as f:
|
||||
try:
|
||||
start = pickle.load(f)
|
||||
except EOFError: # Something went very wrong, file is corrupt?
|
||||
mastodon.status_post("Hello @"+account+" \n unfortunately, your savegame is corrupted or missing",visibility="direct") #The file has been moved or is corrupted
|
||||
os.remove(save_position+account)
|
||||
os.remove(save_position+account+".draughts")
|
||||
logging.warning("%s file corrupted",account)
|
||||
return
|
||||
if start: #The game is started, load other parameters
|
||||
|
@ -119,14 +137,14 @@ def check_message(notification):
|
|||
board = pickle.load(f)
|
||||
if (start == "WAIT"): #The game is not started yet
|
||||
if "quit" in content.lower(): #Game withdrawn
|
||||
os.remove(save_position+account)
|
||||
os.remove(save_position+account+".draughts")
|
||||
mastodon.status_post("Hello @"+account+" \nthe challenge has been withdrawn.",visibility="direct")
|
||||
else: #Lobby is disabled if a challenge request is active
|
||||
mastodon.status_post("Hello @"+account+" \nyou have already challenged someone, type QUIT to withdraw,",visibility="direct")
|
||||
return
|
||||
if "quit" in content.lower(): #The game is quitted
|
||||
os.remove(save_position+black[1:])
|
||||
os.remove(save_position+white[1:])
|
||||
os.remove(save_position+black[1:]+".draughts")
|
||||
os.remove(save_position+white[1:]+".draughts")
|
||||
mastodon.status_post(black+" "+white+" the match was cancelled.",visibility="direct")
|
||||
return
|
||||
if (black == "@"+account and turn == 1) or (white == "@"+account and turn == 0): #Check if the turn is right
|
||||
|
@ -135,7 +153,7 @@ def check_message(notification):
|
|||
mastodon.status_post("@"+account+" \nInvalid move.",visibility="direct")
|
||||
return
|
||||
else:
|
||||
with open(save_position+account,"wb") as f: #Save the updated board
|
||||
with open(save_position+account+".draughts","wb") as f: #Save the updated board
|
||||
pickle.dump("START",f)
|
||||
turn = not turn
|
||||
pickle.dump(black,f)
|
||||
|
@ -155,13 +173,19 @@ def check_message(notification):
|
|||
winner_t = "WHITE"
|
||||
else:
|
||||
winner_t = "BLACK"
|
||||
os.remove(save_position+black[1:])
|
||||
os.remove(save_position+white[1:])
|
||||
os.remove(save_position+black[1:]+".draughts")
|
||||
os.remove(save_position+white[1:]+".draughts")
|
||||
mastodon.status_post("◾: "+black+" ◽: "+white+"\n"+winner_t+" WINS!\n"+dama.draw_checkerboard(board,space,white_norm,white_knight,black_norm,black_knight,empty,column,frstrow),visibility="direct")
|
||||
return
|
||||
else: #We moved in a wrong turn
|
||||
mastodon.status_post("@"+account+" \nIt's not your turn.",visibility="direct")
|
||||
return
|
||||
return
|
||||
|
||||
#Lobby
|
||||
for game in available_games:
|
||||
if game in content.lower():
|
||||
if not os.path.exists(save_position+account+"."+game): #If there is no a savegame file, then lobby mode is activated
|
||||
lobby(notification,content,account,game)
|
||||
|
||||
if __name__ == "__main__":
|
||||
if api_url[:4] != "http":
|
||||
|
|
45
4_engine.py → four_engine.py
Normal file → Executable file
45
4_engine.py → four_engine.py
Normal file → Executable file
|
@ -1,11 +1,11 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
def drawChequerboard(status,players=[],toprow="1234567"):
|
||||
def drawChequerboard(status,players=[],space="░",toprow="1234567"):
|
||||
print(toprow)
|
||||
for row in status:
|
||||
for cell in row:
|
||||
if cell == 0:
|
||||
print("░",end="")
|
||||
print(space,end="")
|
||||
else:
|
||||
try:
|
||||
print(players[cell],end="")
|
||||
|
@ -42,13 +42,45 @@ def checkFour(board,row,col):
|
|||
sumOr = lambda a,b : (a[0]+b[0], a[1]+b[1])
|
||||
orients = { "N":(1,0),"S":(-1,0),"E":(0,1),"W":(0,-1) }
|
||||
player = board[row][col]
|
||||
offX = 0
|
||||
offY = 0
|
||||
#TODO
|
||||
|
||||
points = 0
|
||||
count = 0
|
||||
count += countTokens(board,orients["N"],row,col)
|
||||
count += countTokens(board,orients["S"],row,col)
|
||||
if count >= 3:
|
||||
points +=1
|
||||
count = 0
|
||||
count += countTokens(board,orients["E"],row,col)
|
||||
count += countTokens(board,orients["W"],row,col)
|
||||
if count >= 3:
|
||||
points +=1
|
||||
count = 0
|
||||
count += countTokens(board,sumOr( orients["N"],orients["E"] ),row,col )
|
||||
count += countTokens(board,sumOr( orients["S"],orients["W"] ),row,col )
|
||||
if count >= 3:
|
||||
points +=1
|
||||
count = 0
|
||||
count += countTokens(board,sumOr( orients["N"],orients["W"] ),row,col )
|
||||
count += countTokens(board,sumOr( orients["S"],orients["E"] ),row,col )
|
||||
if count >= 3:
|
||||
points +=1
|
||||
|
||||
|
||||
return points
|
||||
|
||||
def countTokens(board,check,row,col):
|
||||
player = board[row][col]
|
||||
offX = check[0]
|
||||
offY = check[1]
|
||||
count = 0
|
||||
while True:
|
||||
if row+offY < 0 or row+offY >= len(board[row])-1 or col+offX < 0 or col+offX > len(board) or (board[row+offY][col+offX] != player) :
|
||||
break
|
||||
else:
|
||||
count += 1
|
||||
offX += check[0]
|
||||
offY += check[1]
|
||||
return count
|
||||
|
||||
def checkPly(board,row,col,player):
|
||||
if row < 0 or col < 0:
|
||||
return False
|
||||
|
@ -92,6 +124,7 @@ if __name__ == "__main__":
|
|||
if cell == 0:
|
||||
match = True
|
||||
print("Match over")
|
||||
drawChequerboard(board)
|
||||
print("Player 1 scored "+str(points_1)+" points")
|
||||
print("Player 2 scored "+str(points_2)+" points")
|
||||
if points_1 > points_2:
|
2
login.py
2
login.py
|
@ -6,7 +6,7 @@ fileDir = fileDir +"/"
|
|||
|
||||
def login(url):
|
||||
mastodon = Mastodon(
|
||||
access_token = fileDir+"DAMA.SECRET",
|
||||
access_token = fileDir+"DAMA.SECRET.LOCAL",
|
||||
api_base_url = url
|
||||
)
|
||||
return mastodon
|
||||
|
|
Loading…
Reference in a new issue