#TODO #En strategi frö att lägga ut orden #Skirva om library-ord-utdelningen för att ge lite mer random #Räkna crossings #Gör större rutor osv #Things to know #In the wordmatrix empty squares are " " and black (dead) squares are "\n" # import Image import ImageDraw import ImageFont import copy import random import sys import wordlookup #c++ for fast lookups(perhaps more about testing SWIG actually) WORDLIST = "SAOL.txt" SQUARESIZE = 16 XLETTEROFFSET = 3 YLETTEROFFSET = -1 class Korsord: """Contains a crossword imagesd and all the letters and functions for adding new words without breaking the old ones""" #INIT STUFF def __init__(self,sizex, sizey, sqrsize): "two size coordinates" self.size = (sizex*sqrsize,sizey*sqrsize) self.nrsqr = (sizex,sizey) self.sqrsize = sqrsize self.im = Image.new("RGB",self.size,(255,255,255)) #blank crossword self.fontArial = ImageFont.truetype("arial.ttf",16) self.imd = ImageDraw.ImageDraw(self.im) self.wordCounterH = 0 self.wordCounterV = 0 self.crossings = 0 self.buildWordMatrix() # self.im.show() def buildWordMatrix(self): "Build a list with blank spaces that later contains the letters in the crossword" l = [] for x in range(self.nrsqr[1]): l.append(" ") self.wordMatrix = [] for x in range(self.nrsqr[0]): self.wordMatrix.append(copy.copy(l)) self.postHMatrix = [] for x in range(self.nrsqr[0]): self.postHMatrix.append(copy.copy(l)) self.postVMatrix = [] for x in range(self.nrsqr[0]): self.postVMatrix.append(copy.copy(l)) #SHOW AND LETTER STUFF def applyLetters(self): for x in range(self.nrsqr[0]): for y in range(self.nrsqr[1]): self.drawLetter(x,y,self.wordMatrix[x][y].capitalize()) def drawLetter(self,posx,posy,letter): "draw a single letter in a given square" "should probably check letter isn't more than one character" self.imd.text((posx*self.sqrsize+XLETTEROFFSET, posy*self.sqrsize+YLETTEROFFSET), letter, font=self.fontArial, fill=(0,0,0)) def show(self): self.im.show() print "CROSSWORD MADE WITH " + str(self.wordCounterH+self.wordCounterV) + " WORDS" print str(self.wordCounterH) + " HORISONTAL AND " + str(self.wordCounterV) + " VERTICAL" print "CROSSINGS: " + str(self.crossings) # print self.postHMatrix # print self.wordMatrix #BASIC CELLOPERATIONS def fillEmpty(self): for x in range(self.nrsqr[0]): for y in range(self.nrsqr[1]): if self.wordMatrix[x][y]==' ': self.killCell(x,y) def newCell(self, posx, posy): self.imd.rectangle([(posx*self.sqrsize,posy*self.sqrsize),(posx*self.sqrsize+self.sqrsize,posy*self.sqrsize+self.sqrsize)],outline = (0,0,0)) def killCell(self,posx,posy): "make a cell black(dead)" if self.wordMatrix[posx][posy] == ' ': self.imd.rectangle([(posx*self.sqrsize,posy*self.sqrsize),(posx*self.sqrsize+self.sqrsize,posy*self.sqrsize+self.sqrsize)],fill = (0,0,0), outline = (0,0,0)) self.wordMatrix[posx][posy] = '\n' else: print "illeageal fill operation " + str(posx) + " " +str(posy) #cellmatrix might be good for something def newCells(self, posx,posy, lengthx, lengthy): for x in range(lengthx): for y in range(lengthy): self.newCell(posx+x,posy+y) def startCellH(self,posx,posy): if 0>posx-1 or self.wordMatrix[posx-1][posy] == '\n': #if already blacked out return #should never be placed if prvious cell is filled, but we should checkthat too else: self.killCell(posx-1,posy) def startCellV(self,posx,posy): if 0>posy-1 or self.wordMatrix[posx][posy-1] == '\n': #if already blacked out return #should never be placed if prvious cell is filled, but we should checkthat too else: self.killCell(posx,posy-1) def endCellH(self,posx,posy): if self.nrsqr[0]<=posx+1 or self.wordMatrix[posx+1][posy] == '\n': #if already blacked out return if self.wordMatrix[posx+1][posy] != ' ': #already have a letter we have self.imd.rectangle([(posx*self.sqrsize+self.sqrsize-2,posy*self.sqrsize),(posx*self.sqrsize+self.sqrsize-1,posy*self.sqrsize+self.sqrsize-1)],fill = (0,0,0)) return else: self.killCell(posx+1,posy) def endCellV(self,posx,posy): if self.nrsqr[1]<=posy+1 or self.wordMatrix[posx][posy+1] == '\n': #if already blacked out return if self.wordMatrix[posx][posy+1] != ' ': #already have a letter we have self.imd.rectangle([(posx*self.sqrsize,posy*self.sqrsize+self.sqrsize-2),(posx*self.sqrsize+self.sqrsize-1,posy*self.sqrsize+self.sqrsize-1)],fill = (0,0,0)) return else: self.killCell(posx,posy+1) #ADDWORD OPERATIONS def newCellsV(self, posx,posy, word): if len(word)+posy>self.nrsqr[1] or posx<0 or posy<0: return 0 for x in range(len(word)): if self.wordMatrix[posx][posy+x]!=' ' and self.wordMatrix[posx][posy+x] != word[x]: print "Failed attemptV" + word +" "+str(posx) + " " +str(posy) + "+ " + str(x) print self.wordMatrix[posx][posy+x] return "FAIL" self.postVMatrix[posx][posy] = word self.wordCounterV = self.wordCounterV+1 for x in range(len(word)): if self.wordMatrix[posx][posy+x]==' ': self.newCell(posx,posy+x) self.wordMatrix[posx][posy+x]=word[x] else: self.crossings = 1+ self.crossings self.startCellV(posx,posy) self.endCellV(posx,posy+len(word)-1) return 1 def newCellsH(self, posx,posy, word): "horisontell" if len(word)+posx>self.nrsqr[0] or posx<0 or posy<0: return 0 for x in range(len(word)): if self.wordMatrix[posx+x][posy]!=' ' and self.wordMatrix[posx+x][posy] != word[x]: print "Failed attemptH" + word +" "+str(posx) + "+ "+str(x)+" " +str(posy) print self.wordMatrix[posx+x][posy] return "FAIL" self.postHMatrix[posx][posy] = word self.wordCounterH = self.wordCounterH+1 for x in range(len(word)): if self.wordMatrix[posx+x][posy]==' ': self.newCell(posx+x,posy) self.wordMatrix[posx+x][posy]=word[x] else : self.crossings = 1+ self.crossings self.startCellH(posx,posy) self.endCellH(posx+len(word)-1,posy) return 1 #CHECK HOW THINGS LOOK STUFF def getMaskH(self, posx, posy): "get a string with already placed letters" word ="" for x in range(posx,self.nrsqr[0]): if self.wordMatrix[x][posy] == '\n': return word word = word + self.wordMatrix[x][posy] return word def getMaskV(self, posx, posy): "get a string with already placed letters" word ="" for x in range(posy,self.nrsqr[1]): if self.wordMatrix[posx][x] == '\n': return word word = word + self.wordMatrix[posx][x] return word def checkDead(self, posx,posy): if posx-1<0 or posy-1<0: return 'N' if self.wordMatrix[posx][posy] == '\n': return 'N' if (self.wordMatrix[posx][posy-1] == '\n') and self.postVMatrix[posx][posy] == " " : return "V" if self.wordMatrix[posx-1][posy] == '\n' and self.postHMatrix[posx][posy] == " " : return "H" return "N" korsord = Korsord(60,40,SQUARESIZE) #korsord.newCell(20,20) #korsord.newCell(21,21) #korsord.newCells(5,5,2,15) wl = wordlookup.WordList() wl.loadList(WORDLIST) """ while korsord.newCellsV(2,2,wl.getWord(random.randint(0,wl.size())).rstrip()) ==0: continue while korsord.newCellsV(4,1,wl.getWord(random.randint(0,wl.size())).rstrip()) == 0: continue while korsord.newCellsV(6,2,wl.getWord(random.randint(0,wl.size())).rstrip()) == 0: continue mask = wl.findWord(korsord.getMaskH(1,3)) if mask: korsord.newCellsH(1,3,mask.rstrip()) mask = wl.findWord(korsord.getMaskH(0,5)) if mask: korsord.newCellsH(0,5,mask.rstrip()) mask = wl.findWord(korsord.getMaskH(0,6)) if mask: korsord.newCellsH(0,6,mask.rstrip()) mask = wl.findWord(korsord.getMaskH(2,4)) if mask: korsord.newCellsH(2,4,mask.rstrip()) mask = wl.findWord(korsord.getMaskV(7,1)) if mask: korsord.newCellsV(7,1,mask.rstrip()) """ for x in range(100): px = random.randint(0,korsord.nrsqr[0]-1) py = random.randint(0,korsord.nrsqr[1]-1) korsord.killCell(px,py) for px in range(korsord.nrsqr[0]/3,korsord.nrsqr[0]): for py in range(korsord.nrsqr[1]/3,korsord.nrsqr[1]): c = korsord.checkDead(px,py) if c == 'N': continue if c == 'H': mask = korsord.getMaskH(px,py) print "#" + mask+ "#" word = wl.findWord(mask) if word: if "FAIL" == korsord.newCellsH(px,py,word.rstrip()) : print "#" + mask+ "#" korsord.applyLetters() korsord.show() sys.exit() elif c == 'V': mask = korsord.getMaskV(px,py) word = wl.findWord(mask) if word: if "FAIL" == korsord.newCellsV(px,py,word.rstrip()): print mask for x in range(70): px = random.randint(0,korsord.nrsqr[0]-1) py = random.randint(0,korsord.nrsqr[1]-1) korsord.killCell(px,py) for px in range(korsord.nrsqr[0]): for py in range(korsord.nrsqr[1]): c = korsord.checkDead(px,py) if c == 'N': continue if c == 'H': mask = korsord.getMaskH(px,py) word = wl.findWord(mask) if word: if "FAIL" == korsord.newCellsH(px,py,word.rstrip()) : print "#" + mask+ "#" korsord.applyLetters() korsord.show() sys.exit() elif c == 'V': mask = korsord.getMaskV(px,py) word = wl.findWord(mask) if word: if "FAIL" == korsord.newCellsV(px,py,word.rstrip()): print mask korsord.fillEmpty() korsord.show() korsord.applyLetters() korsord.show()