class Board
Board
main class storing, displaying and controling game
Attributes
fields[RW]
player1[RW]
player1Stack[RW]
player2[RW]
player2Stack[RW]
Public Class Methods
new(g, field,sCh,p)
click to toggle source
# File lib/board.rb, line 11 def initialize (g, field,sCh,p) @turn = 0 @game = g #Gosu window @activeObjects = Set.new #active objects to be drawn, updated and clicked @path = p initFields(field) initPlayers(field) initStones addStonesToStack freezeStones markAvailableFields @newWordsCoords = Set.new #set storing coordinates in arrays [x_from,y_from,x_to,y_to] @chooseLetter = false #shoud button for choosing letter for joker be active @checkSpelling = sCh #check spelling @db = SQLite3::Database.new (@path + "/database/vocabulary.db") #database with vocabulary for spell check end
Public Instance Methods
addStonesToStack()
click to toggle source
# File lib/board.rb, line 407 def addStonesToStack #fills player stack with new stones if there is space for them if @turn % 2 == 1 for i in 0..6 if @player1Stack[i].stone == nil && @stones.size > 0 @player1Stack[i].assingStone(@stones[0]) @activeObjects << @stones[0] @stones.delete_at(0) end end else for i in 0..6 if @player2Stack[i].stone == nil && @stones.size > 0 @player2Stack[i].assingStone(@stones[0]) @activeObjects << @stones[0] @stones.delete_at(0) end end end end
availableField(indexX,indexY)
click to toggle source
# File lib/board.rb, line 450 def availableField (indexX,indexY) isFree = @fields[indexX][indexY].stone == nil if !isFree || @stoneChanged #field is occupied and can not be used return false end if @fields[7][7].stone == nil #is starting field empty? if so its free and no other can be used if indexX == 7 && indexY == 7 return true else return false end end #check in possible directions if has neighbour, if has at least one then it can be used hasNeighbour = false hasNeighbour = hasNeighbour || ( 0 <= indexX-1 && 14 >= indexX-1 && 0 <= indexY && 14 >= indexY && @fields[indexX-1][indexY].stone != nil ) hasNeighbour = hasNeighbour || ( 0 <= indexX && 14 >= indexX && 0 <= indexY-1 && 14 >= indexY-1 && @fields[indexX] [indexY-1].stone != nil ) hasNeighbour = hasNeighbour || ( 0 <= indexX && 14 >= indexX && 0 <= indexY+1 && 14 >= indexY+1 && @fields[indexX] [indexY+1].stone != nil ) hasNeighbour = hasNeighbour || ( 0 <= indexX+1 && 14 >= indexX+1 && 0 <= indexY && 14 >= indexY && @fields[indexX+1][indexY].stone != nil ) hasNeighbour end
changeStone(stone)
click to toggle source
# File lib/board.rb, line 473 def changeStone(stone) #returns stone to pouch @activeObjects.delete(stone) #remove stone from @activeObjects @stoneChanged = true #player changed stone -> can not create words returnStonesFromTable #if player already placed stones on board, then remove them @stones << stone #put stone in pouch @stones.shuffle! #shuffle pouch! end
checkConsistency(indexX,indexY)
click to toggle source
# File lib/board.rb, line 369 def checkConsistency (indexX,indexY) #finds all stones properly connected to starting stone and marks them as ok if @fields[indexX][indexY].stone != nil && @fields[indexX][indexY].stone.checked != true @fields[indexX][indexY].stone.checked = true #sets stone checked as connected to starting stone 0 <= indexX-1 && 14 >= indexX-1 && 0 <= indexY && 14 >= indexY && checkConsistency(indexX-1, indexY) 0 <= indexX && 14 >= indexX && 0 <= indexY-1 && 14 >= indexY-1 && checkConsistency(indexX , indexY-1) 0 <= indexX && 14 >= indexX && 0 <= indexY+1 && 14 >= indexY+1 && checkConsistency(indexX , indexY+1) 0 <= indexX+1 && 14 >= indexX+1 && 0 <= indexY && 14 >= indexY && checkConsistency(indexX+1, indexY) else return end true end
checkTable()
click to toggle source
# File lib/board.rb, line 339 def checkTable #check if rules are kept checkConsistency(7,7) #mark separated "islands" of stones repairInconsistency #remove marked separated stones markAvailableFields #mark available fields for placing stones findWords #search for newly added words if @checkSpelling && !spellCheck #check spelling if is required returnStonesFromTable #if spelling is not right return stones to stack return false end countPoints #count and add points for newly added words true end
choosingLetter()
click to toggle source
# File lib/board.rb, line 515 def choosingLetter #evaulate which letter was chosen for joker stone if @game.mouse_x >= 25 && @game.mouse_x <= 115 && @game.mouse_y >= 25 && @game.mouse_y <= 610 x = ((@game.mouse_x-25)/45).to_i y = ((@game.mouse_y-25)/45).to_i @chooseLetter = false chosenLetter = 65 + x*13 + y @jokerStone.imageDown = Gosu::Image.new(@path + "/media/stone" + chosenLetter.chr() + ".png", :tileable => true) @jokerStone = nil end end
clicked()
click to toggle source
# File lib/board.rb, line 541 def clicked #send clicked signal to active objects if @chooseLetter choosingLetter else @activeObjects.each do |i| i.clicked end end end
countPoints()
click to toggle source
# File lib/board.rb, line 302 def countPoints totalPoints = 0 @newWordsCoords.each do |i| wordPoints = 0 wordMultiplicator = 1 #product of multiplicators for whole word length = (i[2]-i[0] + i[1]-i[3]).abs #word lenght dirX = i[2]-i[0] > 0 ? 1 : ((i[2]-i[0]) < 0 ? -1 : 0) dirY = i[3]-i[1] > 0 ? 1 : ((i[3]-i[1]) < 0 ? -1 : 0) for j in 0..length #counts points and bonuses for word y = i[0]+j*dirX x = i[1]+j*dirY wordPoints += @fields[x][y].stone.score * (@fields[x][y].stone.static ? 1 : @fields[x][y].letterValue) #points for word with letter bonues considered wordMultiplicator *= @fields[x][y].wordValue > 0 && !@fields[x][y].stone.static ? @fields[x][y].wordValue : 1 #update of word multiplicator bonus end totalPoints+= wordPoints * wordMultiplicator #update of total points by points of word with word multiplicator bonuses end bonus = 0 #check if player used all stones and can get 50 points bonus if @turn%2 == 1 @player1Stack.each do |i| bonus += i.stone == nil ? 0 : 1 end else @player2Stack.each do |i| bonus += i.stone == nil ? 0 : 1 end end totalPoints += bonus == 0 ? 50 : 0 #assigne points if @turn%2 == 1 @player1.score += totalPoints else @player2.score += totalPoints end end
draw()
click to toggle source
# File lib/board.rb, line 532 def draw #send draw signal to active objects @activeObjects.each do |i| i.draw end if @chooseLetter @allStonesTable.draw(25, 25, 3) end end
findWordInDirection(x,y,dir)
click to toggle source
# File lib/board.rb, line 227 def findWordInDirection(x,y,dir) #find words in direction dir (0/1) containing letter at coords [x,y] a = dir == 1 ? 1 : 0 b = dir == 0 ? 1 : 0 border1 = dir == 1 ? x : y border2 = dir == 1 ? x : y for i in 1..14 if border1 < 14 && @fields[i*a+x][i*b+y].stone != nil #search in positive direction from [x,y] border1+=1 else break end end for i in 1..14 if border2 > 0 && @fields[i*-a+x][i*-b+y].stone != nil #search in negative direction from [x,y] border2-=1 else break end end if dir == 1 #save coords of found word in set @newWordsCoords #since direction is never diagonal, one coord is same for both positions #larger changed coord is always in first part, smaller in second @newWordsCoords << [ y, border1 > border2 ? border2 : border1, y, border1 < border2 ? border2 : border1] else @newWordsCoords << [ border1 > border2 ? border2 : border1,x, border1 < border2 ? border2 : border1, x] end end
findWords()
click to toggle source
# File lib/board.rb, line 256 def findWords #finds newly created words on board @newWordsCoords.clear() #clear set of words found in previous turn for i in 0..14 for j in 0..14 if @fields[i][j].stone != nil && @fields[i][j].stone.static == false if (j+1 < 15 && @fields[i][j+1].stone != nil) || ( j-1 >=0 && @fields[i][j-1].stone != nil) findWordInDirection(i,j,0) #explore in direction 0 end if (i+1 < 15 && @fields[i+1][j].stone != nil) || ( i-1 >=0 && @fields[i-1][j].stone != nil) findWordInDirection(i,j,1) #explore in direction 1 end end end end #exception if only one stone is placed on starting field, otherwise stone has to have always a neighbour if @fields[7][7].stone != nil && @fields[7][8].stone == nil && @fields[8][7].stone == nil && @fields[6][7].stone == nil && @fields[7][6].stone == nil @newWordsCoords << [7,7,7,7] end end
freezeStones()
click to toggle source
# File lib/board.rb, line 384 def freezeStones #marks all stones on table as static and (un)freezes players stacks depending on turn for i in 0..14 for j in 0..14 if @fields[i][j].stone != nil @fields[i][j].stone.static = true end end end val1 = @turn % 2 == 1 ? false : true @player1Stack.each do |i| if i.stone != nil i.stone.static = val1 end end @player2Stack.each do |i| if i.stone != nil i.stone.static = !val1 end end end
initFields(field)
click to toggle source
# File lib/board.rb, line 46 def initFields(field) #initializes board fields - assignes bonuses, fields for stacks and field for changing stones # puts @path + "/media/changeStone.png" @changeField = Field.new(@game.width-60, 10,0,1,Gosu::Image.new(@path + "/media/changeStone.png", :tileable => true)) #field for changing stones @changeField.allowed = true #sets change field to be visible @activeObjects << @changeField @fields = Array.new(15) { Array.new(15, nil) } #2d array containing all fields on board except stacks and change field for i in 0..14 for j in 0..14 @fields[i][j] = Field.new(113+50*i, 27 + 53*j,0,1,field) #create fields on board @activeObjects << @fields[i][j] end end #assigning bonuses to fields @fields[0][0].wordValue = 3 @fields[0][7].wordValue = 3 @fields[0][14].wordValue = 3 @fields[7][0].wordValue = 3 @fields[7][14].wordValue = 3 @fields[14][0].wordValue = 3 @fields[14][7].wordValue = 3 @fields[14][14].wordValue = 3 @fields[1][1].wordValue = 2 @fields[2][2].wordValue = 2 @fields[3][3].wordValue = 2 @fields[4][4].wordValue = 2 @fields[1][13].wordValue = 2 @fields[2][12].wordValue = 2 @fields[3][11].wordValue = 2 @fields[4][10].wordValue = 2 @fields[10][4].wordValue = 2 @fields[11][3].wordValue = 2 @fields[12][2].wordValue = 2 @fields[13][1].wordValue = 2 @fields[10][10].wordValue = 2 @fields[11][11].wordValue = 2 @fields[12][12].wordValue = 2 @fields[13][13].wordValue = 2 @fields[0][3].letterValue = 2 @fields[0][11].letterValue = 2 @fields[2][6].letterValue = 2 @fields[2][8].letterValue = 2 @fields[3][0].letterValue = 2 @fields[3][7].letterValue = 2 @fields[3][14].letterValue = 2 @fields[6][2].letterValue = 2 @fields[6][6].letterValue = 2 @fields[6][8].letterValue = 2 @fields[6][12].letterValue = 2 @fields[7][3].letterValue = 2 @fields[7][11].letterValue = 2 @fields[8][2].letterValue = 2 @fields[8][6].letterValue = 2 @fields[8][8].letterValue = 2 @fields[8][12].letterValue = 2 @fields[11][0].letterValue = 2 @fields[11][7].letterValue = 2 @fields[11][14].letterValue = 2 @fields[12][6].letterValue = 2 @fields[12][8].letterValue = 2 @fields[14][3].letterValue = 2 @fields[14][11].letterValue = 2 @fields[1][5].letterValue = 3 @fields[1][9].letterValue = 3 @fields[5][1].letterValue = 3 @fields[5][5].letterValue = 3 @fields[5][9].letterValue = 3 @fields[5][13].letterValue = 3 @fields[9][1].letterValue = 3 @fields[9][5].letterValue = 3 @fields[9][9].letterValue = 3 @fields[9][13].letterValue = 3 @fields[13][5].letterValue = 3 @fields[13][9].letterValue = 3 end
initPlayers(field)
click to toggle source
# File lib/board.rb, line 28 def initPlayers(field) @player1Stack = Array.new(7) #stack of player 1 @player2Stack = Array.new(7) #stack of player 2 for i in 0..6 #prepare stacks of players @player1Stack[i] = Field.new( 25, 50 + 50*i,0,0,field) @player2Stack[i] = Field.new( @game.width - 75 , @game.height - 50 - 50*i,0,0, field) @activeObjects << @player1Stack[i] @activeObjects << @player2Stack[i] end @player1 = Player.new(10,10,Gosu::Font.new(20),"Player1") #create player 1 @player2 = Player.new(@game.width-80,500,Gosu::Font.new(20),"Player2") #create player 1 @activeObjects << @player1 @activeObjects << @player2 end
initStones()
click to toggle source
# File lib/board.rb, line 128 def initStones() #initializes all stones and table for choosing joker replacement letter @allStonesTable = Gosu::Image.new(@path + "/media/allStones.png", :tileable => true) #image of table for choosing replacement letter for joker @stones = Array.new # "pouch" with all stones #initialization of stones scr = 0 for i in 0..1 @stones << Stone.new(0,0, Gosu::Image.new(@game, @path + "/media/stone_.png", false), @stones, scr, "_", @game, Gosu::Image.new(@game, @path + "/media/stone0.png", false) ) end scr = 1 for i in 0..11 @stones << Stone.new(0,0, Gosu::Image.new(@game, @path + "/media/stoneE.png", false), @stones, scr, "e", @game, Gosu::Image.new(@game, @path + "/media/stone1.png", false) ) end for i in 0..8 @stones << Stone.new(0,0, Gosu::Image.new(@game, @path + "/media/stoneA.png", false), @stones, scr, "a", @game, Gosu::Image.new(@game, @path + "/media/stone1.png", false) ) end for i in 0..8 @stones << Stone.new(0,0, Gosu::Image.new(@game, @path + "/media/stoneI.png", false), @stones, scr, "i", @game, Gosu::Image.new(@game, @path + "/media/stone1.png", false) ) end for i in 0..7 @stones << Stone.new(0,0, Gosu::Image.new(@game, @path + "/media/stoneO.png", false), @stones, scr, "o", @game, Gosu::Image.new(@game, @path + "/media/stone1.png", false) ) end for i in 0..5 @stones << Stone.new(0,0, Gosu::Image.new(@game, @path + "/media/stoneN.png", false), @stones, scr, "n", @game, Gosu::Image.new(@game, @path + "/media/stone1.png", false) ) end for i in 0..5 @stones << Stone.new(0,0, Gosu::Image.new(@game, @path + "/media/stoneR.png", false), @stones, scr, "r", @game, Gosu::Image.new(@game, @path + "/media/stone1.png", false) ) end for i in 0..5 @stones << Stone.new(0,0, Gosu::Image.new(@game, @path + "/media/stoneT.png", false), @stones, scr, "t", @game, Gosu::Image.new(@game, @path + "/media/stone1.png", false) ) end for i in 0..3 @stones << Stone.new(0,0, Gosu::Image.new(@game, @path + "/media/stoneL.png", false), @stones, scr, "l", @game, Gosu::Image.new(@game, @path + "/media/stone1.png", false) ) end for i in 0..3 @stones << Stone.new(0,0, Gosu::Image.new(@game, @path + "/media/stoneS.png", false), @stones, scr, "s", @game, Gosu::Image.new(@game, @path + "/media/stone1.png", false) ) end for i in 0..3 @stones << Stone.new(0,0, Gosu::Image.new(@game, @path + "/media/stoneU.png", false), @stones, scr, "u", @game, Gosu::Image.new(@game, @path + "/media/stone1.png", false) ) end scr = 2 for i in 0..3 @stones << Stone.new(0,0, Gosu::Image.new(@game, @path + "/media/stoneD.png", false), @stones, scr, "d", @game, Gosu::Image.new(@game, @path + "/media/stone2.png", false) ) end for i in 0..2 @stones << Stone.new(0,0, Gosu::Image.new(@game, @path + "/media/stoneG.png", false), @stones, scr, "g", @game, Gosu::Image.new(@game, @path + "/media/stone2.png", false) ) end scr=3 for i in 0..1 @stones << Stone.new(0,0, Gosu::Image.new(@game, @path + "/media/stoneB.png", false), @stones, scr, "b", @game, Gosu::Image.new(@game, @path + "/media/stone3.png", false) ) end for i in 0..1 @stones << Stone.new(0,0, Gosu::Image.new(@game, @path + "/media/stoneC.png", false), @stones, scr, "c", @game, Gosu::Image.new(@game, @path + "/media/stone3.png", false) ) end for i in 0..1 @stones << Stone.new(0,0, Gosu::Image.new(@game, @path + "/media/stoneM.png", false), @stones, scr, "m", @game, Gosu::Image.new(@game, @path + "/media/stone3.png", false) ) end for i in 0..1 @stones << Stone.new(0,0, Gosu::Image.new(@game, @path + "/media/stoneP.png", false), @stones, scr, "p", @game, Gosu::Image.new(@game, @path + "/media/stone3.png", false) ) end scr=4 for i in 0..1 @stones << Stone.new(0,0, Gosu::Image.new(@game, @path + "/media/stoneF.png", false), @stones, scr, "f", @game, Gosu::Image.new(@game, @path + "/media/stone4.png", false) ) end for i in 0..1 @stones << Stone.new(0,0, Gosu::Image.new(@game, @path + "/media/stoneH.png", false), @stones, scr, "h", @game, Gosu::Image.new(@game, @path + "/media/stone4.png", false) ) end for i in 0..1 @stones << Stone.new(0,0, Gosu::Image.new(@game, @path + "/media/stoneV.png", false), @stones, scr, "v", @game, Gosu::Image.new(@game, @path + "/media/stone4.png", false) ) end for i in 0..1 @stones << Stone.new(0,0, Gosu::Image.new(@game, @path + "/media/stoneW.png", false), @stones, scr, "w", @game, Gosu::Image.new(@game, @path + "/media/stone4.png", false) ) end for i in 0..1 @stones << Stone.new(0,0, Gosu::Image.new(@game, @path + "/media/stoneY.png", false), @stones, scr, "y", @game, Gosu::Image.new(@game, @path + "/media/stone4.png", false) ) end @stones << Stone.new(0,0, Gosu::Image.new(@game, @path + "/media/stoneK.png", false), @stones, 5, "k", @game, Gosu::Image.new(@game, @path + "/media/stone5.png", false) ) @stones << Stone.new(0,0, Gosu::Image.new(@game, @path + "/media/stoneJ.png", false), @stones, 8, "j", @game, Gosu::Image.new(@game, @path + "/media/stone8.png", false) ) @stones << Stone.new(0,0, Gosu::Image.new(@game, @path + "/media/stoneX.png", false), @stones, 8, "x", @game, Gosu::Image.new(@game, @path + "/media/stone8.png", false) ) @stones << Stone.new(0,0, Gosu::Image.new(@game, @path + "/media/stoneQ.png", false), @stones, 10, "q", @game, Gosu::Image.new(@game, @path + "/media/stone10.png", false) ) @stones << Stone.new(0,0, Gosu::Image.new(@game, @path + "/media/stoneZ.png", false), @stones, 10, "z", @game, Gosu::Image.new(@game, @path + "/media/stone10.png", false) ) @stones.shuffle! #shuffle stones in "pouch" end
isInDb(word)
click to toggle source
# File lib/board.rb, line 276 def isInDb(word) #tryies to find word in database and returns true/false if it was found/not found isItThere = false res = @db.execute( "select * from vocabulary where word= '#{word}' COLLATE NOCASE" ) do |row| isItThere = true end isItThere end
markAvailableFields()
click to toggle source
# File lib/board.rb, line 427 def markAvailableFields #marks fields which can be used to place stones for i in 0..14 for j in 0..14 @fields[i][j].allowed = availableField(i,j) end end end
nextTurn()
click to toggle source
# File lib/board.rb, line 435 def nextTurn #proceed to next turn if checkTable is ok if !checkTable else if @stones.size > 0 #are there stones in pouch to play with? @turn+=1 #increment turn addStonesToStack #refill player stack freezeStones #freeze stones @stoneChanged = false #reset stoneChanged to default value else @game.gameFinished #end game end end end
placeStone(stone)
click to toggle source
# File lib/board.rb, line 481 def placeStone (stone) #assigne stone to proper field based on its current position in window #potential field coords on board indexX = ((stone.posX-113)/50).to_i indexY = ((stone.posY-27)/53).to_i if stone.posX >= (@game.width-60) && stone.posX <= (@game.width-10) && stone.posY >= 10 && stone.posY <= 60 #if is stone over change stone button -> change stone changeStone(stone) elsif stone.posX >= 113 && stone.posX <= 863 && stone.posY >= 27 && stone.posY <= 796 && availableField(indexX,indexY) && !@stoneChanged #stone is over field on board and player can place stones, place stone @fields[indexX][indexY].assingStone(stone) if stone.score == 0 #if placed stone is joker, then it needs to have assigned letter it's supposed to take place of @chooseLetter = true @jokerStone = stone end else #if stone is not on any field, or over stack -> return stone to players stack if @turn%2 == 1 #player1Stack for i in 0..6 if @player1Stack[i].stone == nil @player1Stack[i].assingStone(stone) break end end else #player2Stack for i in 0..6 if @player2Stack[i].stone == nil @player2Stack[i].assingStone(stone) break end end end end markAvailableFields #mark available fields after last move end
repairInconsistency()
click to toggle source
# File lib/board.rb, line 352 def repairInconsistency #remove marked separated stones for i in 0..14 for j in 0..14 if @fields[i][j].stone != nil && @fields[i][j].stone.checked == false @fields[i][j].stone.myField = nil @fields[i][j].stone.posX = 0 @fields[i][j].stone.posY = 0 placeStone(@fields[i][j].stone) @fields[i][j].stone = nil end if @fields[i][j].stone != nil @fields[i][j].stone.checked = false end end end end
returnStonesFromTable()
click to toggle source
# File lib/board.rb, line 212 def returnStonesFromTable #returns all stones which player placed in current turn for i in 0..14 for j in 0..14 if @fields[i][j].stone != nil && !@fields[i][j].stone.static @fields[i][j].stone.myField = nil @fields[i][j].stone.posX = 0 @fields[i][j].stone.posY = 0 placeStone(@fields[i][j].stone) @fields[i][j].stone = nil end end end end
spellCheck()
click to toggle source
# File lib/board.rb, line 284 def spellCheck #extracts words from board and checks if are present in vocabulary @newWordsCoords.each do |i| length = (i[2]-i[0] + i[1]-i[3]).abs #lenght of word word = "" #word dirX = i[2]-i[0] > 0 ? 1 : ((i[2]-i[0]) < 0 ? -1 : 0) dirY = i[3]-i[1] > 0 ? 1 : ((i[3]-i[1]) < 0 ? -1 : 0) for j in 0..length #contructs the word from stones y = i[0]+j*dirX x = i[1]+j*dirY word << @fields[x][y].stone.letter end if !isInDb(word) #checks if word is in vocabulary return false end end true end
update()
click to toggle source
# File lib/board.rb, line 526 def update #send update signal to active objects @activeObjects.each do |i| i.update end end