#####################################################################################
#
# Copyright (c) Microsoft Corporation. All rights reserved.
#
# This source code is subject to terms and conditions of the Apache License, Version 2.0. A
# copy of the license can be found in the License.html file at the root of this distribution. If
# you cannot locate the Apache License, Version 2.0, please send an email to
# ironpy@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
# by the terms of the Apache License, Version 2.0.
#
# You must not remove this notice, or any other, from this software.
#
#
#####################################################################################
import clr
clr.AddReferenceByPartialName("System.Windows.Forms")
clr.AddReferenceByPartialName("System.Drawing")
from System.Windows.Forms import *
from System.Drawing import *
from quadkey import *
from loadpanel import *
from tiles import *
from copyright import *
class Puzzle(Form):
def __init__(self):
### CREATE CONSTANTS ###
self.TOP_BORDER = 20
self.SIDE_BORDER = 10
self.BOTTOM_BORDER = 60
### CREATE INSTANCE VARIABLES ###
self.gridDimension = 3
self.normalTileDimension = 128
self.tileDimension = self.normalTileDimension
self.grid = []
for i in range(0, self.gridDimension):
self.grid += [[]]
for j in range(0, self.gridDimension):
self.grid[i] += [None]
self.gameInProgress = False
self.clearCacheOnExit = False
self.exitFromMenu = False
self.savedSettings = LoadAllSavedSettings()
self.savedPuzzles = self.savedSettings[0]
self.previewState = self.savedSettings[1]
LoadCache()
if self.savedSettings[2] == True:
TurnOnCache()
else:
TurnOffCache()
### SET UP MENU ###
self.CreateMenu()
### SET UP PANELS ###
self.CreatePanels()
### SET PROPERTIES OF THE FORM ###
self.Text = "Puzzle"
self.BackColor = Color.White
w = self.gridDimension * self.tileDimension + 2 * self.SIDE_BORDER + self.menu.Size.Width
h = self.gridDimension * self.tileDimension + self.TOP_BORDER + self.BOTTOM_BORDER
self.ClientSize = Size(w, h)
self.FormClosing += self.formClosing
self.FormBorderStyle = FormBorderStyle.Fixed3D
self.MaximizeBox = False
self.KeyPreview = True
### PLACE WLL BANNER ###
self.wllPicture = PictureBox()
self.wllPicture.SizeMode = PictureBoxSizeMode.AutoSize
import nt
try:
self.wllPicture.Image = Image.FromFile(nt.getcwd() + "\\banner.bmp")
except:
self.wllPicture.Image = None
self.wllPicture.Location = Point(self.ClientSize.Width - self.wllPicture.Size.Width, self.ClientSize.Height - self.wllPicture.Size.Height)
self.Controls.Add(self.wllPicture)
try:
self.Icon = Icon(nt.getcwd() + "\\icon.ico")
except:
print "Error loading icon.ico"
### SET UP KEYBOARD HANDLER ###
self.KeyDown += self.keyDown
### SET DEFAULT GAME ###
#self.SetBoard('a', 47.55, -122.322, 11, 3)
self.SetBoard('a', 45.05, 14.26, 5, 3)
def CreateMenu(self):
self.menu = MenuStrip()
self.menu.LayoutStyle = ToolStripLayoutStyle.VerticalStackWithOverflow
self.menu.BackColor = Color.White
self.menu.Dock = DockStyle.None
self.menu.Location = Point(0, self.TOP_BORDER)
self.Controls.Add(self.menu)
self.menuPlay = self.CreateMenuItem("play!")
self.menuCreate = self.CreateMenuItem("create")
self.menuLoad = self.CreateMenuItem("load")
self.menuOptions = self.CreateMenuItem("options")
self.menuAbout = self.CreateMenuItem("about")
self.menuExit = self.CreateMenuItem("exit")
self.menuPlay.BackColor = Color.CornflowerBlue
self.menuPlay.ForeColor = Color.White
def CreateMenuItem(self, text):
item = ToolStripMenuItem()
item.Text = text
item.Size = Size(100, 100)
item.Font = Font("Verdana", 8, FontStyle.Bold)
item.Click += self.menuItemClicked
self.menu.Items.Add(item)
return item
def CreateTile(self, i, j, type = None, quadkey = None):
size = Size(self.tileDimension, self.tileDimension)
tile = Tile(i, j, size, type, quadkey)
tile.Location = self.GetLocation(i, j)
self.panelBoard.Controls.Add(tile)
tile.MouseDown += self.mouseDown
tile.MouseUp += self.mouseUp
tile.MouseMove += self.mouseMove
self.grid[i][j] = tile
return tile
def ResetBoardForNewGame(self, dimension):
### clear all tiles
self.panelBoard.Controls.Clear()
### reset grid of tiles
self.gridDimension = dimension
self.grid = []
for i in range(0, self.gridDimension):
self.grid += [[]]
for j in range(0, self.gridDimension):
self.grid[i] += [None]
self.tileDimension = self.normalTileDimension
if dimension == 4:
self.tileDimension = 0.75 * self.tileDimension
self.gameInProgress = False
def CreateShuffleLink(self):
self.linkShuffle = LinkLabel()
self.linkShuffle.Font = Font("Verdana", 12, FontStyle.Bold);
self.linkShuffle.LinkColor = Color.CornflowerBlue
self.linkShuffle.Text = "Shuffle\nto\nStart"
self.linkShuffle.TextAlign = ContentAlignment.MiddleCenter
self.linkShuffle.Size = Size(self.tileDimension, self.tileDimension)
self.linkShuffle.LinkBehavior = LinkBehavior.HoverUnderline
self.linkShuffle.TabStop = False
self.linkShuffle.Location = self.GetLocation(self.gridDimension - 1, self.gridDimension - 1)
self.linkShuffle.Click += self.StartGame
self.panelBoard.Controls.Add(self.linkShuffle)
def PopulateCaptionPlay(self):
self.panelBoard.Controls.Add(self.captionPlay)
self.captionPlay.Text = GetCaption(self.currentGameState[0], self.currentGameState[3], (self.currentGameState[1] + 1, self.currentGameState[2] + 1))
self.RelocateCaptionPlay(None, None)
self.captionPlay.BringToFront()
def PopulateCaptionCreate(self):
self.captionCreate.Text = GetCaption(self.comboType.SelectedItem[0].lower(), self.scrollZoom.Value, self.previewTile[1][1].tile)
self.RelocateCaptionCreate(None, None)
self.captionCreate.BringToFront()
def SetBoard(self, type, lat, lon, level, dimension):
self.ResetBoardForNewGame(dimension)
centerTile = LLToTile(lat, lon, level)
self.currentGameState = [type, centerTile[0]-1, centerTile[1]-1, level, dimension]
self.CreateTile(0, 0, type, TileToQuadkey((centerTile[0]-1, centerTile[1]-1), level))
self.CreateTile(0, 1, type, TileToQuadkey((centerTile[0], centerTile[1]-1), level))
self.CreateTile(0, 2, type, TileToQuadkey((centerTile[0]+1, centerTile[1]-1), level))
self.CreateTile(1, 0, type, TileToQuadkey((centerTile[0]-1, centerTile[1]), level))
self.CreateTile(1, 1, type, TileToQuadkey(centerTile, level))
self.CreateTile(1, 2, type, TileToQuadkey((centerTile[0]+1, centerTile[1]), level))
self.CreateTile(2, 0, type, TileToQuadkey((centerTile[0]-1, centerTile[1]+1), level))
self.CreateTile(2, 1, type, TileToQuadkey((centerTile[0], centerTile[1]+1), level))
if dimension == 4:
self.CreateTile(0, 3, type, TileToQuadkey((centerTile[0]+2, centerTile[1]-1), level))
self.CreateTile(1, 3, type, TileToQuadkey((centerTile[0]+2, centerTile[1]), level))
self.CreateTile(2, 2, type, TileToQuadkey((centerTile[0]+1, centerTile[1]+1), level))
self.CreateTile(2, 3, type, TileToQuadkey((centerTile[0]+2, centerTile[1]+1), level))
self.CreateTile(3, 0, type, TileToQuadkey((centerTile[0]-1, centerTile[1]+2), level))
self.CreateTile(3, 1, type, TileToQuadkey((centerTile[0], centerTile[1]+2), level))
self.CreateTile(3, 2, type, TileToQuadkey((centerTile[0]+1, centerTile[1]+2), level))
self.CreateShuffleLink()
self.PopulateCaptionPlay()
def SetBoardFromCreate(self):
dimension = 3
if self.radio4x4.Checked is True:
dimension = 4
self.ResetBoardForNewGame(dimension)
if self.comboType.SelectedItem == "Road":
type = "r"
elif self.comboType.SelectedItem == "Aerial":
type = "a"
elif self.comboType.SelectedItem == "Hybrid":
type = "h"
level = self.scrollZoom.Value
centerTile = self.previewTile[0][0].tile
self.SetBoardByTile(type, centerTile, level, dimension)
def SetBoardByTile(self, type, tile, level, dimension):
self.ResetBoardForNewGame(dimension)
self.currentGameState = [type, tile[0], tile[1], level, dimension]
for i in range(0, dimension):
for j in range(0, dimension):
if i != (dimension - 1) or j != (dimension - 1):
self.CreateTile(i, j, type, TileToQuadkey((tile[0]+j, tile[1]+i), level))
self.CreateShuffleLink()
self.PopulateCaptionPlay()
def StartGame(self, sender, e):
self.gameInProgress = True
self.Shuffle()
self.linkShuffle.Visible = False
def LoadGame(self, sender, e):
idx = self.panelGames.selectedIndex
if idx < 0 or idx >= len(self.panelGames.buttons):
return
if self.gameInProgress is True:
dr = MessageBox.Show("Quit current game?", "", MessageBoxButtons.YesNo)
if dr == DialogResult.No:
return
puzzle = self.savedPuzzles[idx]
self.menuItemClicked(self.menuPlay, None)
self.SetBoardByTile(puzzle[1], (puzzle[3], puzzle[2]), puzzle[4], puzzle[5])
def ExitGame(self):
if self.gameInProgress is True:
dr = MessageBox.Show("Quit current game?", "", MessageBoxButtons.YesNo)
if dr == DialogResult.No:
return False
if self.clearCacheOnExit is True:
ClearCache()
self.SaveSettings()
self.exitFromMenu = True
self.Close()
def Shuffle(self):
allTiles = []
for i in range(0, self.gridDimension):
for j in range(0, self.gridDimension):
if not self.grid[i][j] is None:
allTiles += [self.grid[i][j]]
allTiles += [None] # dummy tile, used for empty space
from System import Random
rand = Random()
for i in range(0, self.gridDimension):
for j in range(0, self.gridDimension):
idx = rand.Next(len(allTiles))
if allTiles[idx] is None:
self.grid[i][j] = None
else:
self.grid[i][j] = allTiles[idx]
self.grid[i][j].currentRow = i
self.grid[i][j].currentCol = j
self.grid[i][j].Location = self.GetLocation(i, j)
allTiles = allTiles[:idx] + allTiles[idx+1:]
def GetLocation(self, i, j):
x = j * self.tileDimension
y = i * self.tileDimension
return Point(x, y)
def CheckGrid(self):
for i in range(0, self.gridDimension):
for j in range(0, self.gridDimension):
if not self.grid[i][j] is None:
if not self.grid[i][j].isCorrect():
return False
self.gameInProgress = False
self.linkShuffle.Enabled = False
self.linkShuffle.Text = "Nicely\ndone!"
self.linkShuffle.Visible = True
return True
def PopulatePreviewTiles(self):
x = self.previewState[0]
y = self.previewState[1]
level = self.previewState[3]
type = self.comboType.SelectedItem
for i in range(0, 4):
for j in range(0, 4):
tile = (x+j, y+i)
quadkey = TileToQuadkey(tile, level)
self.previewTile[i][j].quadkey = quadkey
self.previewTile[i][j].tile = tile
self.previewTile[i][j].Image = GetImage(type[0].lower(), quadkey)
self.PopulateCaptionCreate()
def SaveSettings(self):
import clr
clr.AddReference("System.Xml")
from System.Xml import XmlDocument
import nt
xmldoc = XmlDocument()
try:
xmldoc.Load(nt.getcwd() + "\load.xml")
except:
print "Error reading load.xml"
return
nodelist = xmldoc.GetElementsByTagName("Cache")
a = xmldoc.CreateAttribute("allow")
if self.checkCache.Checked is True:
a.Value = "true"
else:
a.Value = "false"
nodelist.Item(0).Attributes.Append(a)
nodelist = xmldoc.GetElementsByTagName("TopLeftPreviewTile")
a = xmldoc.CreateAttribute("x")
a.Value = str(self.previewTile[0][0].tile[0])
nodelist.Item(0).Attributes.Append(a)
a = xmldoc.CreateAttribute("y")
a.Value = str(self.previewTile[0][0].tile[1])
nodelist.Item(0).Attributes.Append(a)
a = xmldoc.CreateAttribute("dimension")
if self.radio3x3.Checked is True:
a.Value = "3"
else:
a.Value = "4"
nodelist.Item(0).Attributes.Append(a)
a = xmldoc.CreateAttribute("level")
a.Value = str(self.scrollZoom.Value)
nodelist.Item(0).Attributes.Append(a)
try:
xmldoc.Save(nt.getcwd() + "\load.xml")
except:
print "Error writing load.xml"
def SaveCurrentGame(self, caption):
import clr
clr.AddReference("System.Xml")
from System.Xml import *
import nt
xmldoc = XmlDocument()
try:
xmldoc.Load(nt.getcwd() + "\load.xml")
except:
print "Error reading load.xml"
return
nodeSavedGames = xmldoc.GetElementsByTagName("SavedGames")
nodeNewGame = xmldoc.CreateElement("Game")
a = xmldoc.CreateAttribute("caption")
a.Value = caption
nodeNewGame.Attributes.Append(a)
a = xmldoc.CreateAttribute("type")
a.Value = self.currentGameState[0]
nodeNewGame.Attributes.Append(a)
a = xmldoc.CreateAttribute("x")
a.Value = str(self.currentGameState[1])
nodeNewGame.Attributes.Append(a)
a = xmldoc.CreateAttribute("y")
a.Value = str(self.currentGameState[2])
nodeNewGame.Attributes.Append(a)
a = xmldoc.CreateAttribute("level")
a.Value = str(self.currentGameState[3])
nodeNewGame.Attributes.Append(a)
a = xmldoc.CreateAttribute("dimension")
a.Value = str(self.currentGameState[4])
nodeNewGame.Attributes.Append(a)
nodeSavedGames[0].AppendChild(nodeNewGame)
try:
xmldoc.Save(nt.getcwd() + "\load.xml")
except:
print "Error writing load.xml"
### GUI HEAVY LIFTING ###
def CreatePanels(self):
self.panelBoard = Panel()
self.panelBoard.Size = Size(self.gridDimension * self.tileDimension, self.gridDimension * self.tileDimension)
self.panelBoard.Location = Point(self.menu.Size.Width + self.SIDE_BORDER, self.TOP_BORDER)
self.panelBoard.BackColor = Color.White
self.Controls.Add(self.panelBoard)
self.panelCreate = Panel()
self.panelCreate.Size = Size(self.gridDimension * self.tileDimension, self.gridDimension * self.tileDimension)
self.panelCreate.Location = Point(self.menu.Size.Width + self.SIDE_BORDER, self.TOP_BORDER)
self.panelCreate.BackColor = Color.LightSteelBlue
self.Controls.Add(self.panelCreate)
self.panelLoad = Panel()
self.panelLoad.Size = Size(self.gridDimension * self.tileDimension, self.gridDimension * self.tileDimension)
self.panelLoad.Location = Point(self.menu.Size.Width + self.SIDE_BORDER, self.TOP_BORDER)
self.panelLoad.BackColor = Color.LightSteelBlue
self.Controls.Add(self.panelLoad)
self.panelOptions = Panel()
self.panelOptions.Size = Size(self.gridDimension * self.tileDimension, self.gridDimension * self.tileDimension)
self.panelOptions.Location = Point(self.menu.Size.Width + self.SIDE_BORDER, self.TOP_BORDER)
self.panelOptions.BackColor = Color.LightSteelBlue
self.Controls.Add(self.panelOptions)
self.panelAbout = Panel()
self.panelAbout.Size = Size(self.gridDimension * self.tileDimension, self.gridDimension * self.tileDimension)
self.panelAbout.Location = Point(self.menu.Size.Width + self.SIDE_BORDER, self.TOP_BORDER)
self.panelAbout.BackColor = Color.LightSteelBlue
self.Controls.Add(self.panelAbout)
self.panels = [self.panelBoard, self.panelCreate, self.panelLoad, self.panelOptions, self.panelAbout]
### create labels for captions
self.captionPlay = Label()
self.captionCreate = Label()
self.captionPlay.AutoSize = self.captionCreate.AutoSize = True
self.captionPlay.Font = self.captionCreate.Font = Font("Arial", 9)
self.captionPlay.BackColor = self.captionCreate.BackColor = Color.White #Color.CornflowerBlue
self.captionPlay.ForeColor = self.captionCreate.ForeColor = Color.Black #Color.White
self.panelBoard.Controls.Add(self.captionPlay)
self.panelCreate.Controls.Add(self.captionCreate)
### populate Create panel
self.buttonDown = Button()
self.buttonDown.BackColor = Color.White
self.buttonDown.Anchor = AnchorStyles.Bottom
self.buttonDown.FlatStyle = FlatStyle.Flat
self.buttonDown.Size = Size(25, 25)
x = self.panelCreate.Size.Width / 2 - self.buttonDown.Size.Width / 2
y = self.panelCreate.Size.Height - self.buttonDown.Size.Height - 5
self.buttonDown.Location = Point(x, y)
self.buttonDown.MouseDown += self.arrowButtonMouseDown
self.buttonDown.MouseUp += self.arrowButtonMouseUp
self.buttonDown.MouseDown += self.previewMoveDown
self.panelCreate.Controls.Add(self.buttonDown)
self.buttonUp = Button()
self.buttonUp.BackColor = Color.White
self.buttonUp.Anchor = AnchorStyles.Bottom
self.buttonUp.FlatStyle = FlatStyle.Flat
self.buttonUp.Size = Size(25, 25)
y = self.buttonDown.Location.Y - self.buttonDown.Height - 2
self.buttonUp.Location = Point(x, y)
self.buttonUp.MouseDown += self.arrowButtonMouseDown
self.buttonUp.MouseUp += self.arrowButtonMouseUp
self.buttonUp.MouseDown += self.previewMoveUp
self.panelCreate.Controls.Add(self.buttonUp)
self.buttonLeft = Button()
self.buttonLeft.BackColor = Color.White
self.buttonLeft.Anchor = AnchorStyles.Bottom
self.buttonLeft.FlatStyle = FlatStyle.Flat
self.buttonLeft.Size = Size(25, 25)
x = self.buttonDown.Location.X - self.buttonDown.Size.Width - 2
y = self.buttonDown.Location.Y - 0.5 * self.buttonDown.Size.Height
self.buttonLeft.Location = Point(x, y)
self.buttonLeft.MouseDown += self.arrowButtonMouseDown
self.buttonLeft.MouseUp += self.arrowButtonMouseUp
self.buttonLeft.MouseDown += self.previewMoveLeft
self.panelCreate.Controls.Add(self.buttonLeft)
self.buttonRight = Button()
self.buttonRight.BackColor = Color.White
self.buttonRight.Anchor = AnchorStyles.Bottom
self.buttonRight.FlatStyle = FlatStyle.Flat
self.buttonRight.Size = Size(25, 25)
x = self.buttonDown.Location.X + self.buttonDown.Size.Width + 2
self.buttonRight.Location = Point(x, y)
self.buttonRight.MouseDown += self.arrowButtonMouseDown
self.buttonRight.MouseUp += self.arrowButtonMouseUp
self.buttonRight.MouseDown += self.previewMoveRight
self.panelCreate.Controls.Add(self.buttonRight)
self.scrollZoom = HScrollBar()
self.scrollZoom.Anchor = AnchorStyles.Bottom
w = 135
self.scrollZoom.Size = Size(w, 25)
self.scrollZoom.Location = Point(9, self.buttonLeft.Location.Y)
self.scrollZoom.Minimum = 3
self.scrollZoom.Maximum = 19
self.scrollZoom.LargeChange = 1
self.panelCreate.Controls.Add(self.scrollZoom)
self.comboType = ComboBox()
self.comboType.Font = Font("Verdana", 8)
self.comboType.Size = Size(83, 21)
x = self.scrollZoom.Location.X
y = self.scrollZoom.Location.Y - self.comboType.Size.Height - 3
self.comboType.Location = Point(x, y)
self.comboType.Anchor = AnchorStyles.Bottom
self.comboType.Items.Add("Road")
self.comboType.Items.Add("Aerial")
self.comboType.Items.Add("Hybrid")
self.comboType.SelectedIndex = 1
self.comboType.SelectedIndexChanged += self.previewTypeChanged
self.panelCreate.Controls.Add(self.comboType)
self.radio3x3 = RadioButton()
self.radio3x3.BackColor = Color.White
self.radio3x3.Anchor = AnchorStyles.Bottom
self.radio3x3.Font = Font("Verdana", 8)
self.radio3x3.Text = "3x3"
x = self.buttonRight.Location.X + self.buttonRight.Size.Width + 15
y = self.buttonUp.Location.Y + 9
self.radio3x3.Location = Point(x, y)
self.radio3x3.Size = Size(46, 17)
self.radio3x3.Checked = True
self.radio3x3.CheckedChanged += self.previewGridSizeChanged
self.panelCreate.Controls.Add(self.radio3x3)
self.radio4x4 = RadioButton()
self.radio4x4.BackColor = Color.White
self.radio4x4.Anchor = AnchorStyles.Bottom
self.radio4x4.Font = Font("Verdana", 8)
self.radio4x4.Text = "4x4"
y = self.buttonDown.Location.Y + 1
self.radio4x4.Location = Point(x, y)
self.radio4x4.Size = Size(46, 17)
self.radio4x4.CheckedChanged += self.previewGridSizeChanged
self.panelCreate.Controls.Add(self.radio4x4)
self.buttonCreate = Button()
self.buttonCreate.BackColor = Color.White
self.buttonCreate.Anchor = AnchorStyles.Bottom
x = self.radio3x3.Location.X + self.radio3x3.Size.Width + 10
y = self.scrollZoom.Location.Y
self.buttonCreate.Location = Point(x, y)
self.buttonCreate.Size = Size(71, 25)
self.buttonCreate.Font = Font("Verdana", 10)
self.buttonCreate.Text = "Create"
self.buttonCreate.Click += self.createNewGame
self.panelCreate.Controls.Add(self.buttonCreate)
self.previewTile = [[],[],[],[]]
# TODO: error handling
if self.previewState[2] == 3:
tileDim = self.normalTileDimension
else:
tileDim = 0.75 * self.normalTileDimension
self.scrollZoom.Value = self.previewState[3]
for i in range(0, 3):
for j in range(0, 3):
self.previewTile[i] += [RichTile(tileDim)]
x = j * tileDim
y = i * tileDim
self.previewTile[i][j].Location = Point(x, y)
self.panelCreate.Controls.Add(self.previewTile[i][j])
i = 3
y = 3 * 0.75 * self.normalTileDimension
for j in range(0, 4):
self.previewTile[i] += [RichTile(0.75 * self.normalTileDimension)]
x = j * 0.75 * self.normalTileDimension
self.previewTile[i][j].Location = Point(x, y)
self.previewTile[i][j].BackColor = Color.Black
self.panelCreate.Controls.Add(self.previewTile[i][j])
if self.previewState[2] == 3:
self.previewTile[i][j].Visible = False
j = 3
for i in range(0, 3):
self.previewTile[i] += [RichTile(0.75 * self.normalTileDimension)]
y = i * 0.75 * self.normalTileDimension
self.previewTile[i][j].Location = Point(x, y)
self.previewTile[i][j].BackColor = Color.Black
self.panelCreate.Controls.Add(self.previewTile[i][j])
if self.previewState[2] == 3:
self.previewTile[i][j].Visible = False
if self.previewState[2] == 4:
self.radio4x4.Checked = True
self.PopulatePreviewTiles()
# attach event after create gui
self.scrollZoom.ValueChanged += self.scrollZoomChanged
### populate Load panel
self.panelGames = LoadGamePanel()
self.panelGames.Location = Point(10, 10)
self.panelGames.Size = Size(270, self.panelLoad.Size.Height - 23 - 20)
self.panelGames.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Bottom
self.panelLoad.Controls.Add(self.panelGames)
for game in self.savedPuzzles:
b = SavedGameButton(game[0], game[2], game[3], game[1], game[4], game[5])
self.panelGames.AddButton(b)
self.buttonLoad = Button()
self.buttonLoad.BackColor = Color.White
self.buttonLoad.Text = "Load Puzzle"
self.buttonLoad.Font = Font("Verdana", 10)
self.buttonLoad.Size = Size(100, 23)
x = self.panelGames.Location.X
y = self.panelLoad.Size.Height - self.buttonLoad.Size.Height - 10
self.buttonLoad.Location = Point(x, y)
self.buttonLoad.Anchor = AnchorStyles.Left | AnchorStyles.Bottom
self.buttonLoad.Click += self.LoadGame
self.panelLoad.Controls.Add(self.buttonLoad)
### populate Options panel
self.labelTileSize = Label()
self.labelTileSize.AutoSize = True
self.labelTileSize.Font = Font("Verdana", 10, FontStyle.Bold)
self.labelTileSize.Text = "Tile Size"
self.labelTileSize.Location = Point(25, 15)
self.panelOptions.Controls.Add(self.labelTileSize)
self.radio50 = RadioButton()
self.radio50.Font = Font("Verdana", 10)
self.radio50.Text = "50%"
self.radio50.Size = Size(55, 20)
x = self.labelTileSize.Location.X + self.labelTileSize.Size.Width + 15
y = self.labelTileSize.Location.Y
self.radio50.Location = Point(x, y)
self.radio50.Checked = True
self.radio50.CheckedChanged += self.tileSizeChanged
self.panelOptions.Controls.Add(self.radio50)
self.radio75 = RadioButton()
self.radio75.Font = Font("Verdana", 10)
self.radio75.Text = "75%"
self.radio75.Size = Size(55, 20)
x = self.radio50.Location.X + self.radio50.Size.Width + 2
self.radio75.Location = Point(x, y)
self.radio75.CheckedChanged += self.tileSizeChanged
self.panelOptions.Controls.Add(self.radio75)
self.radio100 = RadioButton()
self.radio100.Font = Font("Verdana", 10)
self.radio100.Text = "100%"
self.radio100.Size = Size(65, 20)
x = self.radio75.Location.X + self.radio75.Size.Width + 2
self.radio100.Location = Point(x, y)
self.radio100.CheckedChanged += self.tileSizeChanged
self.panelOptions.Controls.Add(self.radio100)
self.checkCache = CheckBox()
self.checkCache.AutoSize = True
self.checkCache.Font = Font("Verdana", 10, FontStyle.Bold)
self.checkCache.Text = "Allow caching"
x = self.labelTileSize.Location.X
y = self.labelTileSize.Location.Y + self.labelTileSize.Size.Height + 20
self.checkCache.Location = Point(x, y)
if self.savedSettings[2] == True:
self.checkCache.Checked = True
self.checkCache.CheckedChanged += self.toggleCache
self.panelOptions.Controls.Add(self.checkCache)
self.buttonClearCache = Button()
self.buttonClearCache.BackColor = Color.White
self.buttonClearCache.AutoSize = True
self.buttonClearCache.Font = Font("Verdana", 10)
self.buttonClearCache.Text = "Clear Cache"
x = self.checkCache.Location.X + self.checkCache.Size.Width + 10
y -= 4
self.buttonClearCache.Location = Point(x, y)
self.buttonClearCache.Click += self.buttonClearCacheClicked
self.panelOptions.Controls.Add(self.buttonClearCache)
### populate About panel
text = Label()
text.Text = "Ravi Chugh"
text.Text += "\nrkc@seas.upenn.edu"
text.Text += "\n"
text.Text += "\nwritten in IronPython on .NET 2.0"
text.Text += "\ntiles served by Virtual Earth"
text.Text += "\n"
text.Text += "\nVirtual Earth terms of use:"
text.Text += "\nwww.microsoft.com/virtualearth/control/terms.mspx"
text.Text += "\n"
text.Text += "\nimage providers:"
text.Text += "\nlocal.live.com/Help/en-us/Credits.htm"
text.TextAlign = ContentAlignment.MiddleCenter
text.Size = self.panelAbout.Size
text.Font = Font("Verdana", 10)
text.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Right
self.panelAbout.Controls.Add(text)
def ResizeEverything(self, tileDim):
self.tileDimension = self.normalTileDimension = tileDim
if self.gridDimension == 4:
self.tileDimension = 0.75 * self.tileDimension
w = self.gridDimension * self.tileDimension + 2 * self.SIDE_BORDER + self.menu.Size.Width
h = self.gridDimension * self.tileDimension + self.TOP_BORDER + self.BOTTOM_BORDER
self.ClientSize = Size(w, h)
self.wllPicture.Location = Point(self.ClientSize.Width - self.wllPicture.Size.Width, self.ClientSize.Height - self.wllPicture.Size.Height)
for panel in self.panels:
w = self.gridDimension * self.tileDimension
panel.Size = Size(w, w)
for i in range(0, self.gridDimension):
for j in range(0, self.gridDimension):
if not self.grid[i][j] is None:
self.grid[i][j].Size = Size(self.tileDimension, self.tileDimension)
self.grid[i][j].Location = self.GetLocation(i, j)
### resize preview tiles
if self.previewState[2] == 3:
tileDim = self.normalTileDimension
else:
tileDim = 0.75 * self.normalTileDimension
for i in range(0, 3):
for j in range(0, 3):
x = j * tileDim
y = i * tileDim
self.previewTile[i][j].Location = Point(x, y)
self.previewTile[i][j].Size = Size(tileDim, tileDim)
i = 3
y = 3 * 0.75 * self.normalTileDimension
for j in range(0, 4):
x = j * 0.75 * self.normalTileDimension
self.previewTile[i][j].Location = Point(x, y)
self.previewTile[i][j].Size = Size(tileDim, tileDim)
j = 3
for i in range(0, 3):
self.previewTile[i] += [RichTile(0.75 * self.normalTileDimension)]
y = i * 0.75 * self.normalTileDimension
self.previewTile[i][j].Location = Point(x, y)
self.previewTile[i][j].Size = Size(tileDim, tileDim)
self.linkShuffle.Size = Size(self.tileDimension, self.tileDimension)
self.linkShuffle.Location = self.GetLocation(self.gridDimension - 1, self.gridDimension - 1)
self.RelocateCaptionPlay(None, None)
self.RelocateCaptionCreate(None, None)
def RelocateCaptionPlay(self, sender, e):
self.captionPlay.Location = Point(self.panelBoard.Size.Width - self.captionPlay.Size.Width, 0)
def RelocateCaptionCreate(self, sender, e):
self.captionCreate.Location = Point(self.panelCreate.Size.Width - self.captionCreate.Size.Width, 0)
### EVENT HANDLERS ###
def formClosing(self, sender, e):
if self.exitFromMenu is True:
return
if self.gameInProgress is True:
dr = MessageBox.Show("Quit current game?", "", MessageBoxButtons.YesNo)
if dr == DialogResult.No:
e.Cancel = True
return
if self.clearCacheOnExit is True:
ClearCache()
self.SaveSettings()
def menuItemClicked(self, sender, e):
if sender is self.menuExit:
self.ExitGame()
return
for i in range(0, self.menu.Items.Count):
self.menu.Items[i].BackColor = Color.White
self.menu.Items[i].ForeColor = Color.Black
sender.BackColor = Color.CornflowerBlue
sender.ForeColor = Color.White
for i in range(0, len(self.panels)):
self.panels[i].Visible = False
if sender is self.menuPlay: self.panels[0].Visible = True
elif sender is self.menuCreate: self.panels[1].Visible = True
elif sender is self.menuLoad: self.panels[2].Visible = True
elif sender is self.menuOptions: self.panels[3].Visible = True
elif sender is self.menuAbout: self.panels[4].Visible = True
def mouseDown(self, sender, e):
if self.gameInProgress is False:
return
x = sender.currentRow
y = sender.currentCol
if x > 0 and self.grid[x-1][y] is None:
sender.direction = "up"
elif x < self.gridDimension - 1 and self.grid[x+1][y] is None:
sender.direction = "down"
elif y > 0 and self.grid[x][y-1] is None:
sender.direction = "left"
elif y < self.gridDimension - 1 and self.grid[x][y+1] is None:
sender.direction = "right"
if not sender.direction is None:
sender.beingDragged = True
sender.initialClick = e.Location
def mouseUp(self, sender, e):
if not sender.initialClick is None and e.X is sender.initialClick.X and e.Y is sender.initialClick.Y:
if sender.direction is "right":
self.slideRight(sender)
elif sender.direction is "left":
self.slideLeft(sender)
elif sender.direction is "up":
self.slideUp(sender)
else:
self.slideDown(sender)
elif sender.direction is "right":
if sender.Location.X < (sender.currentCol + 0.5) * self.tileDimension:
self.snapBack(sender)
else:
self.slideRight(sender)
elif sender.direction is "left":
if sender.Location.X > (sender.currentCol - 0.5) * self.tileDimension:
sender.Location = Point((sender.currentCol) * self.tileDimension, sender.Location.Y)
else:
self.slideLeft(sender)
elif sender.direction is "up":
if sender.Location.Y > (sender.currentRow - 0.5) * self.tileDimension:
sender.Location = Point(sender.Location.X, sender.currentRow * self.tileDimension)
else:
self.slideUp(sender)
elif sender.direction is "down":
if sender.Location.Y < (sender.currentRow + 0.5) * self.tileDimension:
sender.Location = Point(sender.Location.X, sender.currentRow * self.tileDimension)
else:
self.slideDown(sender)
sender.direction = None
sender.beingDragged = False
sender.initialClick = None
def mouseMove(self, sender, e):
x = sender.Location.X
y = sender.Location.Y
if sender.beingDragged:
if sender.direction is "right":
dX = e.X - sender.initialClick.X
if x + dX >= (sender.currentCol) * self.tileDimension:
if x + dX <= (sender.currentCol + 1) * self.tileDimension:
x += dX
elif sender.direction is "left":
dX = e.X - sender.initialClick.X
if x + dX >= (sender.currentCol - 1) * self.tileDimension:
if x + dX <= (sender.currentCol) * self.tileDimension:
x += dX
elif sender.direction is "up":
dY = e.Y - sender.initialClick.Y
if y + dY >= (sender.currentRow - 1) * self.tileDimension:
if y + dY <= (sender.currentRow) * self.tileDimension:
y = sender.Location.Y + e.Y - sender.initialClick.Y
elif sender.direction is "down":
dY = e.Y - sender.initialClick.Y
if y + dY >= (sender.currentRow) * self.tileDimension:
if y + dY <= (sender.currentRow + 1) * self.tileDimension:
y += dY
sender.Location = Point(x, y)
def snapBack(self, sender):
sender.Location = Point(sender.currentCol * self.tileDimension, sender.currentRow * self.tileDimension)
def slideLeft(self, sender):
self.grid[sender.currentRow][sender.currentCol] = None
sender.currentCol -= 1
self.grid[sender.currentRow][sender.currentCol] = sender
sender.Location = Point(sender.currentCol * self.tileDimension, sender.currentRow * self.tileDimension)
self.CheckGrid()
def slideRight(self, sender):
self.grid[sender.currentRow][sender.currentCol] = None
sender.currentCol += 1
self.grid[sender.currentRow][sender.currentCol] = sender
sender.Location = Point(sender.currentCol * self.tileDimension, sender.currentRow * self.tileDimension)
self.CheckGrid()
def slideUp(self, sender):
self.grid[sender.currentRow][sender.currentCol] = None
sender.currentRow -= 1
self.grid[sender.currentRow][sender.currentCol] = sender
sender.Location = Point(sender.currentCol * self.tileDimension, sender.currentRow * self.tileDimension)
self.CheckGrid()
def slideDown(self, sender):
self.grid[sender.currentRow][sender.currentCol] = None
sender.currentRow += 1
self.grid[sender.currentRow][sender.currentCol] = sender
sender.Location = Point(sender.currentCol * self.tileDimension, sender.currentRow * self.tileDimension)
self.CheckGrid()
def keyDown(self, sender, e):
if self.panels[0].Visible is True:
self.keyDownForGame(sender, e)
elif self.panels[1].Visible is True:
self.keyDownForCreate(sender, e)
def keyDownForGame(self, sender, e):
if self.gameInProgress is False:
return
if e.KeyCode == Keys.Left:
for i in range(0, self.gridDimension):
for j in range(0, self.gridDimension - 1):
if self.grid[i][j] is None:
self.slideLeft(self.grid[i][j+1])
return
elif e.KeyCode == Keys.Right:
for i in range(0, self.gridDimension):
for j in range(1, self.gridDimension):
if self.grid[i][j] is None:
self.slideRight(self.grid[i][j-1])
return
elif e.KeyCode == Keys.Up:
for i in range(0, self.gridDimension - 1):
for j in range(0, self.gridDimension):
if self.grid[i][j] is None:
self.slideUp(self.grid[i+1][j])
return
elif e.KeyCode == Keys.Down:
for i in range(1, self.gridDimension):
for j in range(0, self.gridDimension):
if self.grid[i][j] is None:
self.slideDown(self.grid[i-1][j])
return
def keyDownForCreate(self, sender, e):
e.SuppressKeyPress = True
e.Handled = True
if e.KeyCode == Keys.Left:
self.previewMoveLeft()
elif e.KeyCode == Keys.Right:
self.previewMoveRight()
elif e.KeyCode == Keys.Up:
self.previewMoveUp()
elif e.KeyCode == Keys.Down:
self.previewMoveDown()
def arrowButtonMouseDown(self, sender, e):
sender.BackColor = Color.SteelBlue
def arrowButtonMouseUp(self, sender, e):
sender.BackColor = Color.White
def tileSizeChanged(self, sender, e):
# two CheckedChanged events are fired when choosing another radio button
# so ignore one
if sender.Checked is False:
return
if self.radio50.Checked:
self.ResizeEverything(0.50 * 256)
elif self.radio75.Checked:
self.ResizeEverything(0.75 * 256)
elif self.radio100.Checked:
self.ResizeEverything(256)
def previewTypeChanged(self, sender, e):
type = self.comboType.SelectedItem[0].lower()
for i in range(0, 4):
for j in range(0, 4):
self.previewTile[i][j].Image = GetImage(type, self.previewTile[i][j].quadkey)
self.PopulateCaptionCreate()
def previewGridSizeChanged(self, sender, e):
if sender is False:
return
if sender is self.radio3x3:
tileDim = self.normalTileDimension
else:
tileDim = 0.75 * self.normalTileDimension
i = 3
for j in range(0, 4):
self.previewTile[i][j].Visible = True
j = 3
for i in range(0, 3):
self.previewTile[i][j].Visible = True
for i in range(0, 3):
for j in range(0, 3):
self.previewTile[i][j].Size = Size(tileDim, tileDim)
x = j * tileDim
y = i * tileDim
self.previewTile[i][j].Location = Point(x, y)
if self.radio3x3 is sender:
self.previewState[2] = 3
else:
self.previewState[2] = 4
def scrollZoomChanged(self, sender, e):
oldLevel = self.previewState[3]
newLevel = sender.Value
deltaLevel = newLevel - oldLevel
if deltaLevel > 0:
#self.previewState[0] = self.previewState[0] * 2 + int(0.5 * (MaxTiles(newLevel) - MaxTiles(oldLevel)))
#self.previewState[1] = self.previewState[1] * 2 + int(0.5 * (MaxTiles(newLevel) - MaxTiles(oldLevel)))
self.previewState[0] = (self.previewState[0] + 1) * 2 * deltaLevel - 1
self.previewState[1] = (self.previewState[1] + 1) * 2 * deltaLevel - 1
elif deltaLevel < 0:
self.previewState[0] = (self.previewState[0]) / (-2 * deltaLevel)
self.previewState[1] = (self.previewState[1]) / (-2 * deltaLevel)
self.previewState[0] = self.previewState[0] / MaxTiles(newLevel)
self.previewState[1] = self.previewState[1] / MaxTiles(newLevel)
self.previewState[3] = newLevel
self.PopulatePreviewTiles()
def previewMoveRight(self, sender = None, e = None):
for i in range(0, 4):
for j in range(0, 3):
self.previewTile[i][j].Image = self.previewTile[i][j+1].Image
self.previewTile[i][j].quadkey = self.previewTile[i][j+1].quadkey
self.previewTile[i][j].tile = self.previewTile[i][j+1].tile
type = self.comboType.SelectedItem
for i in range(0, 4):
tile = (self.previewTile[i][2].tile[0] + 1, self.previewTile[i][2].tile[1])
quadkey = TileToQuadkey(tile, self.previewState[3])
self.previewTile[i][3].Image = GetImage(type[0].lower(), quadkey)
self.previewTile[i][3].quadkey = quadkey
self.previewTile[i][3].tile = tile
def previewMoveLeft(self, sender = None, e = None):
for i in range(0, 4):
for j in range(3, 0, -1):
self.previewTile[i][j].Image = self.previewTile[i][j-1].Image
self.previewTile[i][j].quadkey = self.previewTile[i][j-1].quadkey
self.previewTile[i][j].tile = self.previewTile[i][j-1].tile
type = self.comboType.SelectedItem
for i in range(0, 4):
tile = (self.previewTile[i][1].tile[0] - 1, self.previewTile[i][1].tile[1])
quadkey = TileToQuadkey(tile, self.previewState[3])
self.previewTile[i][0].Image = GetImage(type[0].lower(), quadkey)
self.previewTile[i][0].quadkey = quadkey
self.previewTile[i][0].tile = tile
def previewMoveDown(self, sender = None, e = None):
for i in range(0, 3):
for j in range(0, 4):
self.previewTile[i][j].Image = self.previewTile[i+1][j].Image
self.previewTile[i][j].quadkey = self.previewTile[i+1][j].quadkey
self.previewTile[i][j].tile = self.previewTile[i+1][j].tile
type = self.comboType.SelectedItem
for j in range(0, 4):
tile = (self.previewTile[3][j].tile[0], self.previewTile[3][j].tile[1] + 1)
quadkey = TileToQuadkey(tile, self.previewState[3])
self.previewTile[3][j].Image = GetImage(type[0].lower(), quadkey)
self.previewTile[3][j].quadkey = quadkey
self.previewTile[3][j].tile = tile
def previewMoveUp(self, sender = None, e = None):
for i in range(3, 0, -1):
for j in range(0, 4):
self.previewTile[i][j].Image = self.previewTile[i-1][j].Image
self.previewTile[i][j].quadkey = self.previewTile[i-1][j].quadkey
self.previewTile[i][j].tile = self.previewTile[i-1][j].tile
type = self.comboType.SelectedItem
for j in range(0, 4):
tile = (self.previewTile[0][j].tile[0], self.previewTile[0][j].tile[1] - 1)
quadkey = TileToQuadkey(tile, self.previewState[3])
self.previewTile[0][j].Image = GetImage(type[0].lower(), quadkey)
self.previewTile[0][j].quadkey = quadkey
self.previewTile[0][j].tile = tile
def toggleCache(self, sender, e):
if self.checkCache.Checked is True:
MessageBox.Show("Take a look at the Caching section of the tutorial")
TurnOnCache()
else:
TurnOffCache()
def buttonClearCacheClicked(self, sender, e):
self.clearCacheOnExit = True
def createNewGame(self, sender, e):
if self.gameInProgress is True:
dr = MessageBox.Show("Quit current game?", "", MessageBoxButtons.YesNo)
if dr == DialogResult.No:
return
self.SetBoardFromCreate()
self.menuItemClicked(self.menuPlay, None)
def Main():
Application.Run(Puzzle())
if __name__ == "__main__":
Main()
else:
import winforms