1. import wx
  2. import math
  3.  
  4. class SketchFrame(wx.Frame):
  5. def __init__(self, parent):
  6.  
  7. wx.Frame.__init__(self, parent, -1, "Catan Simulator",size=(560,640))
  8. self.sketch = SketchWindow(self, -1)
  9.  
  10. class SketchWindow(wx.Window):
  11.  
  12. def __init__ (self, parent,ID):
  13.  
  14. wx.Window.__init__(self, parent, ID)
  15. self.Buffer = None
  16.  
  17. #Create Array of starting indexes
  18. self.linelen = 50
  19. rowlens=[4,5,6,7,6,5,4]
  20. index=0
  21.  
  22. self.hexes={}
  23.  
  24. for x in range(0,38):
  25. self.hexes[x]={}
  26. self.hexes[x]["number"]=x
  27.  
  28. #seed
  29. self.hexes[0]["xpos"]=0
  30. self.hexes[0]["ypos"]=175
  31.  
  32. #Row Starts
  33. self.hexes[1]["xpos"]=self.hexes[0]["xpos"]
  34. self.hexes[1]["ypos"]=self.hexes[0]["ypos"]
  35. self.hexes[5]["xpos"]=self.hexes[0]["xpos"]
  36. self.hexes[5]["ypos"]=self.hexes[0]["ypos"]+math.sin(math.radians(60))*self.linelen*2
  37. self.hexes[10]["xpos"]=self.hexes[0]["xpos"]
  38. self.hexes[10]["ypos"]=self.hexes[5]["ypos"]+math.sin(math.radians(60))*self.linelen*2
  39. self.hexes[16]["xpos"]=self.hexes[0]["xpos"]
  40. self.hexes[16]["ypos"]=self.hexes[10]["ypos"]+math.sin(math.radians(60))*self.linelen*2
  41. self.hexes[23]["xpos"]=self.hexes[16]["xpos"]+math.cos(math.radians(60))*self.linelen+self.linelen
  42. self.hexes[23]["ypos"]=self.hexes[16]["ypos"]+math.sin(math.radians(60))*self.linelen
  43. self.hexes[29]["xpos"]=self.hexes[23]["xpos"]+math.cos(math.radians(60))*self.linelen+self.linelen
  44. self.hexes[29]["ypos"]=self.hexes[23]["ypos"]+math.sin(math.radians(60))*self.linelen
  45. self.hexes[34]["xpos"]=self.hexes[29]["xpos"]+math.cos(math.radians(60))*self.linelen+self.linelen
  46. self.hexes[34]["ypos"]=self.hexes[29]["ypos"]+math.sin(math.radians(60))*self.linelen
  47.  
  48. for z in range(1,38):
  49. try:
  50. self.hexes[z]["xpos"] = self.hexes[z]["xpos"]
  51. except KeyError:
  52. self.hexes[z]["xpos"] = self.hexes[z-1]["xpos"]+math.cos(math.radians(60))*self.linelen+self.linelen
  53. self.hexes[z]["ypos"] = self.hexes[z-1]["ypos"]-math.sin(math.radians(60))*self.linelen
  54.  
  55. for i in [1,2,3,4,5,9,10,15,16,22,23,28,29,33,34,35,36,37]:
  56. self.hexes[i]["landtype"]="water"
  57.  
  58. self.Bind(wx.EVT_PAINT, self.OnPaint)
  59. self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBack)
  60. self.Bind(wx.EVT_LEFT_UP, self.OnLeftClick)
  61. self.Bind(wx.EVT_RIGHT_UP, self.OnRightClick)
  62.  
  63. def OnRightClick(self, event):
  64. pos=event.GetPosition()
  65. clicked=self.hexidentifier(pos[0],pos[1])
  66. if len(clicked) != 1:
  67. return
  68. else:
  69. self.cycledice(clicked[0])
  70. event.Skip()
  71.  
  72. def cycledice(self, hexnum):
  73. if "diceval" not in self.hexes[hexnum]:
  74. self.hexes[hexnum]['diceval'] = "2"
  75. elif self.hexes[hexnum]['diceval'] == "2":
  76. self.hexes[hexnum]['diceval'] = "3"
  77. elif self.hexes[hexnum]['diceval'] == "3":
  78. self.hexes[hexnum]['diceval'] = "4"
  79. elif self.hexes[hexnum]['diceval'] == "4":
  80. self.hexes[hexnum]['diceval'] = "5"
  81. elif self.hexes[hexnum]['diceval'] == "5":
  82. self.hexes[hexnum]['diceval'] = "6"
  83. elif self.hexes[hexnum]['diceval'] == "6":
  84. self.hexes[hexnum]['diceval'] = "8"
  85. elif self.hexes[hexnum]['diceval'] == "8":
  86. self.hexes[hexnum]['diceval'] = "9"
  87. elif self.hexes[hexnum]['diceval'] == "9":
  88. self.hexes[hexnum]['diceval'] = "10"
  89. elif self.hexes[hexnum]['diceval'] == "10":
  90. self.hexes[hexnum]['diceval'] = "11"
  91. elif self.hexes[hexnum]['diceval'] == "11":
  92. self.hexes[hexnum]['diceval'] = "12"
  93. elif self.hexes[hexnum]['diceval'] == "12":
  94. del self.hexes[hexnum]['diceval']
  95.  
  96. dc = wx.ClientDC(self)
  97. self.DrawDiceCircles(dc)
  98.  
  99. def OnLeftClick(self, event):
  100. pos=event.GetPosition()
  101. clicked=self.hexidentifier(pos[0],pos[1])
  102. if len(clicked) != 1:
  103. return
  104. else:
  105. self.cycleland(clicked[0])
  106. event.Skip()
  107.  
  108. def cycleland(self, hexnum):
  109. if "landtype" not in self.hexes[hexnum]:
  110. self.hexes[hexnum]['landtype'] = "mountain"
  111. elif self.hexes[hexnum]['landtype'] == "mountain":
  112. self.hexes[hexnum]['landtype'] = "forest"
  113. elif self.hexes[hexnum]['landtype'] == "forest":
  114. self.hexes[hexnum]['landtype'] = "yellow plain"
  115. elif self.hexes[hexnum]['landtype'] == "yellow plain":
  116. self.hexes[hexnum]['landtype'] = "green meadow"
  117. elif self.hexes[hexnum]['landtype'] == "green meadow":
  118. self.hexes[hexnum]['landtype'] = "clay"
  119. elif self.hexes[hexnum]['landtype'] == "clay":
  120. self.hexes[hexnum]['landtype'] = "desert"
  121. elif self.hexes[hexnum]['landtype'] == "desert":
  122. self.hexes[hexnum]['landtype'] = "water"
  123. elif self.hexes[hexnum]['landtype'] == "water":
  124. del self.hexes[hexnum]['landtype']
  125.  
  126. dc = wx.ClientDC(self)
  127.  
  128. self.fillhex(dc, hexnum, "black")
  129. self.DrawDiceCircles(dc)
  130.  
  131. def hexidentifier(self, xpos, ypos):
  132. valids=[]
  133.  
  134. for hexnum in range(1, 38):
  135. points=[]
  136. points.append([self.hexes[hexnum]["xpos"],self.hexes[hexnum]["ypos"]])
  137. points.append([points[0][0]+math.cos(math.radians(-60))*self.linelen, points[0][1]+math.sin(math.radians(-60))*self.linelen])
  138. points.append([points[1][0]+math.cos(math.radians(0))*self.linelen, points[1][1]+math.sin(math.radians(0))*self.linelen])
  139. points.append([points[2][0]+math.cos(math.radians(60))*self.linelen, points[2][1]+math.sin(math.radians(60))*self.linelen])
  140. points.append([points[3][0]+math.cos(math.radians(120))*self.linelen, points[3][1]+math.sin(math.radians(120))*self.linelen])
  141. points.append([points[4][0]+math.cos(math.radians(180))*self.linelen, points[4][1]+math.sin(math.radians(180))*self.linelen])
  142. points.append([points[5][0]+math.cos(math.radians(240))*self.linelen, points[5][1]+math.sin(math.radians(240))*self.linelen])
  143.  
  144. n = len(points)
  145. inside = False
  146.  
  147. p1x,p1y = points[0]
  148. for i in range(n+1):
  149. p2x,p2y = points[i % n]
  150. if ypos > min(p1y,p2y):
  151. if ypos <= max(p1y,p2y):
  152. if xpos <= max(p1x,p2x):
  153. if p1y != p2y:
  154. xinters = (ypos-p1y)*(p2x-p1x)/(p2y-p1y)+p1x
  155. if p1x == p2x or xpos <= xinters:
  156. inside = not inside
  157. p1x,p1y = p2x,p2y
  158. if inside == True:
  159. valids.append(hexnum)
  160. return valids
  161.  
  162. def InitBuffer(self):
  163. size=self.GetClientSize()
  164. # if buffer exists and size hasn't changed do nothing
  165. if self.Buffer is not None and self.Buffer.GetWidth() == size.width and self.Buffer.GetHeight() == size.height:
  166. return False
  167.  
  168. self.Buffer=wx.EmptyBitmap(size.width,size.height)
  169. dc=wx.MemoryDC()
  170. dc.SelectObject(self.Buffer)
  171. dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
  172. dc.Clear()
  173. self.DrawBoard(dc)
  174. self.fillall(dc)
  175. self.DrawDiceCircles(dc)
  176. dc.SelectObject(wx.NullBitmap)
  177. return True
  178.  
  179. def DrawBoard(self, dc):
  180. degs=[-60,0,60,120,180,240]
  181. for z in range(1,38):
  182. xpos=self.hexes[z]["xpos"]
  183. ypos=self.hexes[z]["ypos"]
  184. for d in degs:
  185. destx=xpos+math.cos(math.radians(d))*self.linelen
  186. desty=ypos+math.sin(math.radians(d))*self.linelen
  187. dc.DrawLine(xpos, ypos, destx, desty)
  188. xpos=destx
  189. ypos=desty
  190.  
  191. def DrawDiceCircles(self,dc):
  192. for i in range(1,38):
  193. if "landtype" not in self.hexes[i]:
  194. continue
  195. if "diceval" not in self.hexes[i]:
  196. self.fillhex(dc, i, "black")
  197. continue
  198. if self.hexes[i]["landtype"] in ["water", "desert"]:
  199. continue
  200. xstart = self.hexes[i]["xpos"]+math.cos(math.radians(60))*self.linelen+.5*self.linelen
  201. ystart = self.hexes[i]["ypos"]
  202. dc.SetPen(wx.Pen("black", 2))
  203. dc.SetBrush(wx.Brush("White"))
  204. dc.DrawCircle(xstart, ystart, 10)
  205. if "diceval" not in self.hexes[i]:
  206. continue
  207. xoff=4
  208. if self.hexes[i]["diceval"] in ["10", "11", "12"]:
  209. xoff = xoff + 4
  210. dc.SetPen(wx.Pen("black", 2))
  211. dc.SetBrush(wx.Brush("White"))
  212. dc.DrawText(self.hexes[i]["diceval"], xstart-xoff, ystart-7)
  213.  
  214.  
  215. def OnEraseBack(self, event):
  216. pass # do nothing to avoid flicker
  217.  
  218. def OnPaint(self, event):
  219. if self.InitBuffer():
  220. self.Refresh() # buffer changed paint in next event, this paint event may be old
  221. return
  222.  
  223. dc = wx.PaintDC(self)
  224. dc.DrawBitmap(self.Buffer, 0, 0)
  225. self.DrawBoard(dc)
  226. self.fillall(dc)
  227. self.DrawDiceCircles(dc)
  228. #self.Drawcircle(dc)
  229.  
  230. def fillall(self, dc, color="black"):
  231. for i in range(1,38):
  232. self.fillhex(dc, i, color)
  233.  
  234. def fillhex(self, dc, hexnum, color="black"):
  235. degs=[-60,0,60,120,180,240]
  236. dc.SetPen(wx.Pen(color, 2))
  237. if "landtype" not in self.hexes[hexnum]:
  238. dc.SetBrush(wx.Brush("Gray"))
  239. elif self.hexes[hexnum]["landtype"]=="water":
  240. dc.SetBrush(wx.Brush("Cyan"))
  241. elif self.hexes[hexnum]["landtype"]=="forest":
  242. dc.SetBrush(wx.Brush("FOREST GREEN"))
  243. elif self.hexes[hexnum]["landtype"]=="yellow plain":
  244. dc.SetBrush(wx.Brush("Yellow"))
  245. elif self.hexes[hexnum]["landtype"]=="clay":
  246. dc.SetBrush(wx.Brush("Red"))
  247. elif self.hexes[hexnum]["landtype"]=="mountain":
  248. dc.SetBrush(wx.Brush("Dark Slate Gray"))
  249. elif self.hexes[hexnum]["landtype"]=="green meadow":
  250. dc.SetBrush(wx.Brush("Lime Green"))
  251. elif self.hexes[hexnum]["landtype"]=="desert":
  252. dc.SetBrush(wx.Brush("Wheat"))
  253. points=[]
  254. points.append([self.hexes[hexnum]["xpos"],self.hexes[hexnum]["ypos"]])
  255. points.append([points[0][0]+math.cos(math.radians(-60))*self.linelen, points[0][1]+math.sin(math.radians(-60))*self.linelen])
  256. points.append([points[1][0]+math.cos(math.radians(0))*self.linelen, points[1][1]+math.sin(math.radians(0))*self.linelen])
  257. points.append([points[2][0]+math.cos(math.radians(60))*self.linelen, points[2][1]+math.sin(math.radians(60))*self.linelen])
  258. points.append([points[3][0]+math.cos(math.radians(120))*self.linelen, points[3][1]+math.sin(math.radians(120))*self.linelen])
  259. points.append([points[4][0]+math.cos(math.radians(180))*self.linelen, points[4][1]+math.sin(math.radians(180))*self.linelen])
  260. points.append([points[5][0]+math.cos(math.radians(240))*self.linelen, points[5][1]+math.sin(math.radians(240))*self.linelen])
  261. #print points
  262. dc.DrawPolygon(points)
  263.  
  264. if __name__=='__main__':
  265. app=wx.PySimpleApp()
  266. frame=SketchFrame(None)
  267. frame.Show(True)
  268. app.MainLoop()