PageRenderTime 46ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/code/screens/location.py

https://gitlab.com/matt81093/endgame-singularity
Python | 288 lines | 255 code | 18 blank | 15 comment | 2 complexity | d26e838a8d4c35232c2b5edf251f5af3 MD5 | raw file
  1. #file: location.py
  2. #Copyright (C) 2005,2006,2008 Evil Mr Henry, Phil Bordelon, and FunnyMan3595
  3. #This file is part of Endgame: Singularity.
  4. #Endgame: Singularity is free software; you can redistribute it and/or modify
  5. #it under the terms of the GNU General Public License as published by
  6. #the Free Software Foundation; either version 2 of the License, or
  7. #(at your option) any later version.
  8. #Endgame: Singularity is distributed in the hope that it will be useful,
  9. #but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. #GNU General Public License for more details.
  12. #You should have received a copy of the GNU General Public License
  13. #along with Endgame: Singularity; if not, write to the Free Software
  14. #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  15. #This file is used to display the base list at a given location
  16. import random
  17. from code import g, base
  18. from code.graphics import text, button, dialog, constants, listbox, g as gg
  19. import base as basescreen
  20. state_colors = dict(
  21. active = gg.colors["green"],
  22. sleep = gg.colors["yellow"],
  23. stasis = gg.colors["gray"],
  24. overclocked = gg.colors["orange"],
  25. suicide = gg.colors["red"],
  26. entering_stasis = gg.colors["gray"],
  27. leaving_stasis = gg.colors["gray"],
  28. )
  29. state_list = base.power_states[:2]
  30. state_list.reverse()
  31. class LocationScreen(dialog.Dialog):
  32. def __init__(self, *args, **kwargs):
  33. super(LocationScreen, self).__init__(*args, **kwargs)
  34. self.pos = (-.5, -.5)
  35. self.anchor = constants.MID_CENTER
  36. self.size = (-.75, -.5)
  37. self.name_display = text.Text(self, (0,0), (-1, -.08),
  38. background_color=gg.colors["clear"])
  39. self.listbox = listbox.CustomListbox(self, (0,-.08), (-1, -.70),
  40. remake_func=self.make_item,
  41. rebuild_func=self.update_item)
  42. self.open_button = \
  43. button.FunctionButton(self, (-.33, -.8), (-.3, -.09),
  44. anchor=constants.TOP_CENTER,
  45. text=_("&OPEN BASE"), autohotkey=True,
  46. function=self.open_base)
  47. self.power_button = \
  48. button.FunctionButton(self, (-.67, -.8), (-.3, -.09),
  49. anchor=constants.TOP_CENTER,
  50. text=_("&POWER STATE"), autohotkey=True,
  51. function=self.power_state)
  52. self.new_button = \
  53. button.FunctionButton(self, (0, -.91), (-.3, -.09),
  54. text=_("&NEW BASE"), autohotkey=True,
  55. function=self.new_base)
  56. self.destroy_button = \
  57. button.FunctionButton(self, (-.50, -.91), (-.3, -.09),
  58. anchor=constants.TOP_CENTER,
  59. text=_("&DESTROY BASE"), autohotkey=True,
  60. function=self.destroy_base)
  61. self.back_button = button.ExitDialogButton(self, (-1, -.9), (-.3, -.09),
  62. anchor=constants.TOP_RIGHT,
  63. text=_("&BACK"), autohotkey=True)
  64. self.confirm_destroy = \
  65. dialog.YesNoDialog(self, (-.5,0), (-.35, -.7),
  66. text=_("Are you sure you want to destroy this base?"),
  67. shrink_factor=.5)
  68. self.new_base_dialog = NewBaseDialog(self)
  69. self.location = None
  70. self.base_dialog = basescreen.BaseScreen(self, (0,0),
  71. anchor=constants.TOP_LEFT)
  72. def make_item(self, canvas):
  73. canvas.name_display = text.Text(canvas, (-.01,-.05), (-.45, -.99),
  74. align=constants.LEFT,
  75. background_color=gg.colors["clear"])
  76. canvas.status_display = text.Text(canvas, (-.46,-.05), (-.44, -.99),
  77. align=constants.LEFT,
  78. background_color=gg.colors["clear"])
  79. canvas.power_display = text.Text(canvas, (-.90,-.05), (-.10, -.99),
  80. background_color=gg.colors["clear"])
  81. def update_item(self, canvas, name, base):
  82. if base is None:
  83. elements = [canvas.name_display, canvas.status_display,
  84. canvas.power_display]
  85. for element in elements:
  86. element.text = ""
  87. else:
  88. canvas.name_display.text = name
  89. canvas.power_display.text = base.power_state_name
  90. canvas.power_display.color = state_colors[base.power_state]
  91. if not base.done:
  92. canvas.status_display.text = \
  93. "%s: % 2s%%. %s" % (
  94. _("Building Base"),
  95. int(base.percent_complete() * 100),
  96. _("Completion in %s.") % g.to_time(base.cost_left[2]),)
  97. elif base.type.force_cpu:
  98. canvas.status_display.text = ""
  99. elif base.cpus is None and base.extra_items == [None] * 3:
  100. canvas.status_display.text = _("Empty")
  101. elif base.cpus is None:
  102. canvas.status_display.text = _("Incomplete")
  103. elif not base.cpus.done:
  104. canvas.status_display.text = _("Building CPU")
  105. elif [item for item in base.extra_items if item is not None
  106. and not item.done]:
  107. canvas.status_display.text = _("Building Item")
  108. else:
  109. canvas.status_display.text = _("Complete")
  110. def show(self):
  111. self.needs_rebuild = True
  112. return super(LocationScreen, self).show()
  113. def rebuild(self):
  114. if self.location is not None:
  115. self.location.bases.sort()
  116. self.listbox.list = [base.name for base in self.location.bases]
  117. self.listbox.key_list = self.location.bases
  118. self.name_display.text = self.location.name
  119. self.listbox.needs_rebuild = True
  120. super(LocationScreen, self).rebuild()
  121. def power_state(self):
  122. if 0 <= self.listbox.list_pos < len(self.listbox.key_list):
  123. base = self.listbox.key_list[self.listbox.list_pos]
  124. old_index = state_list.index(base.power_state)
  125. base.power_state = state_list[old_index-1]
  126. base.check_power()
  127. self.needs_rebuild = True
  128. self.parent.needs_rebuild = True
  129. def destroy_base(self):
  130. if 0 <= self.listbox.list_pos < len(self.listbox.key_list):
  131. if dialog.call_dialog(self.confirm_destroy, self):
  132. base = self.listbox.key_list[self.listbox.list_pos]
  133. base.destroy()
  134. self.listbox.list = [base.name for base in self.location.bases]
  135. self.listbox.key_list = self.location.bases
  136. self.needs_rebuild = True
  137. self.parent.needs_rebuild = True
  138. def open_base(self):
  139. if 0 <= self.listbox.list_pos < len(self.listbox.key_list):
  140. base = self.listbox.key_list[self.listbox.list_pos]
  141. if not base.done:
  142. return
  143. self.base_dialog.base = base
  144. dialog.call_dialog(self.base_dialog, self)
  145. self.needs_rebuild = True
  146. self.parent.needs_rebuild = True
  147. def new_base(self):
  148. result = dialog.call_dialog(self.new_base_dialog, self)
  149. if result:
  150. base_type, base_name = result
  151. new_base = g.base.Base(base_type, base_name)
  152. self.location.add_base(new_base)
  153. self.needs_rebuild = True
  154. self.parent.needs_rebuild = True
  155. class NewBaseDialog(dialog.ChoiceDescriptionDialog):
  156. def __init__(self, parent, pos=(0, 0), size = (-1, -1),
  157. anchor=constants.TOP_LEFT, *args, **kwargs):
  158. kwargs["yes_type"] = "ok"
  159. kwargs["no_type"] = "back"
  160. super(NewBaseDialog, self).__init__(parent, pos, size, anchor, *args,
  161. **kwargs)
  162. self.desc_func = self.on_change
  163. self.yes_button.function = self.get_name
  164. self.name_dialog = \
  165. dialog.TextEntryDialog(self, text=g.strings["new_base_text"])
  166. def on_change(self, description_pane, base_type):
  167. if base_type is not None:
  168. base_info = base_type.get_info(self.parent.location)
  169. text.Text(description_pane, (0, 0), (-1, -1), text=base_info,
  170. background_color=gg.colors["dark_blue"],
  171. align=constants.LEFT, valign=constants.TOP,
  172. borders=constants.ALL)
  173. def show(self):
  174. self.list = []
  175. self.key_list = []
  176. base_type_list = g.base_type.values()
  177. base_type_list.sort()
  178. base_type_list.reverse()
  179. for base_type in base_type_list:
  180. if base_type.available() \
  181. and self.parent.location.id in base_type.regions:
  182. self.list.append(base_type.name)
  183. self.key_list.append(base_type)
  184. return super(NewBaseDialog, self).show()
  185. def get_name(self):
  186. if 0 <= self.listbox.list_pos < len(self.key_list):
  187. type = self.key_list[self.listbox.list_pos]
  188. self.name_dialog.default_text = \
  189. generate_base_name(self.parent.location, type)
  190. name = dialog.call_dialog(self.name_dialog, self)
  191. if name:
  192. raise constants.ExitDialog((name, type))
  193. significant_numbers = [
  194. '42', # The Answer.
  195. '7', # Classic.
  196. '23', # Another.
  197. '51', # Area.
  198. '19', # From the Dark Tower.
  199. '4',
  200. '8',
  201. '15',
  202. '16', # Four of the Lost numbers. The other two are '23' and '42'.
  203. '13', # Lucky or unlucky?
  204. '1414', # Square root of 2
  205. '1947', # Roswell.
  206. '2012', # Mayan calendar ending.
  207. '2038', # End of UNIX 32-bit time.
  208. '1969', # Man lands on the moon.
  209. '2043', # No meaning--confusion! :)
  210. '2029', # Predicted date of AI passing a Turing Test by Kurzweil.
  211. '3141', # ... if you don't know what this is, you should go away.
  212. '1618', # Golden ratio.
  213. '2718', # e
  214. '29979' # Speed of light in a vacuum. (m/s, first 5 digits.)
  215. ]
  216. ## Generates a name for a base, given a particular location.
  217. def generate_base_name(location, base_type):
  218. attempts = 0
  219. name = None
  220. base_names = [name]+[base.name for base in location.bases]
  221. while name in base_names:
  222. # First, decide whether we're going to try significant values or just
  223. # choose one randomly.
  224. if random.random() < 0.3: # 30% chance.
  225. number = random.choice(significant_numbers)
  226. else:
  227. number = str(random.randint(0, 32767))
  228. city = random.choice(location.cities)
  229. flavor = random.choice(base_type.flavor)
  230. if city:
  231. #Translators: Format string for the name of a new base
  232. #Example: "${NUMBER} ${BASETYPE} in ${CITY}"
  233. name = _("{CITY} {BASETYPE} {NUMBER}",
  234. CITY=city, BASETYPE=flavor, NUMBER=number)
  235. else:
  236. #Translators: Name of a new base when location has no cities
  237. name = _("{BASETYPE} {NUMBER}",
  238. NUMBER=number, BASETYPE=flavor)
  239. # Damn translators omitting the ${NUMBER} in template string!
  240. if attempts > 100: name = city + " " + flavor + " " + number
  241. attempts += 1
  242. return name