Vega strike Python Modules doc  0.5.1
Documentation of the " Modules " folder of Vega strike
 All Data Structures Namespaces Files Functions Variables
dynamic_news.py
Go to the documentation of this file.
1 
2 import VS
3 import vsrandom
4 import string
5 import stardate
6 import debug
7 
9  """A class the provides a query mechanism, for each
10  instance, that will return the specified system's
11  faction, name, or parent sector."""
12  SECTOR_SYSTEM = 1
13  SECTOR = 2
14  SYSTEM = 3
15  FACTION = 4
16 
17  def __init__(self, system=VS.getSystemFile()):
18  self.system = system
19  self.faction = VS.GetGalaxyFaction(self.system)
20 
21  def getInfo(self, inf_type=False):
22  """Returns the information corresponding to the
23  given class variable."""
24  try:
25  [sec, sys] = self.system.split('/')
26  except:
27  sec = self.system
28  sys = self.system
29  if not inf_type:
30  return self.system
31  elif inf_type == self.SECTOR:
32  return sec
33  elif inf_type == self.SECTOR_SYSTEM:
34  return self.system
35  elif inf_type == self.SYSTEM:
36  return sys
37  elif inf_type == self.FACTION:
38  return self.faction
39  else:
40  raise ValueError("Invalid information type specified")
41 
42 def LookupRealName(oldname,faction):
43  import VS
44  newname=VS.LookupUnitStat(oldname,faction,"Name")
45  if len(newname)==0:
46  return oldname
47  return newname
48 
49 
51  """Provides functions that handle the translation of a
52  news item using a relevant event tuple."""
53  STARDATE_TEXT = "\\\\\\\This story was first broadcast on: "
54 
55  def __init__(self, dynamic_data):
56  self.dynamic_data = dynamic_data
57  self.item = None
58  self.vars = None
59  self.rand_int = None
60 
61  def lookupInfo(self, var, tag):
62  """Returns the information corresponding to the
63  given var and tag pair."""
64  try:
65  return self.vars[var][tag]
66  except:
67  try:
68  results = self.dynamic_data.getFactionData(self.vars[var]['faction'], tag)
69  except:
70  st = 'ERROR_%s_%s'%(var,tag)#this is in case there is a typo like 'docketat'
71  debug.error(st)
72  results=['ERROR_%s_%s'%(var,tag)]
73  return results[self.rand_int % len(results)]
74 
75  def translateWord(self, word):
76  """Determines if the word given is a variable set,
77  and if so returns the substitute information."""
78  if word.find('VAR_') == -1:
79  return word
80  try:
81  [pre,var,tag] = word.split("_")
82  except:
83  return word
84  pre = pre[:pre.find('VAR')]
85  tagnopun = str()
86  for letter in tag:
87  if letter not in string.punctuation:
88  tagnopun+=letter
89  else:
90  break
91  return pre + self.formatText(self.lookupInfo(var, tagnopun)) + tag[len(tagnopun):]
92 
93  def translateItem(self, item, news_tuple, docked_faction):
94  """Using the given item and information, returns a
95  fully translated version of the item."""
96  self.rand_int = news_tuple[NewsManager.RANDOM_INTEGER_INDEX]
97  self.item = item[2].split()
98  self.vars = dict()
99  stardat_ = dict()
100  if news_tuple[NewsManager.STARDATE_INDEX] == 0:
101  stardat_['value'] = VS.getStarTime()
102  else:
103  stardat_['value'] = news_tuple[NewsManager.STARDATE_INDEX]
104  self.vars['stardate'] = stardat_
105  aggressor = dict()
106  aggressor['faction'] = news_tuple[NewsManager.AGGRESSOR_INDEX]
107  aggressor['FG'] = news_tuple[NewsManager.AGGRESSOR_FLIGHTGROUP_INDEX]
108  aggressor['FGtype'] = LookupRealName(news_tuple[NewsManager.AGGRESSOR_SHIPTYPE_INDEX],aggressor['faction'])
109  self.vars['aggressor'] = aggressor
110  defender = dict()
111  defender['faction'] = news_tuple[NewsManager.DEFENDER_INDEX]
112  defender['FG'] = news_tuple[NewsManager.DEFENDER_FLIGHTGROUP_INDEX]
113  defender['FGtype'] = LookupRealName(news_tuple[NewsManager.DEFENDER_SHIPTYPE_INDEX],defender['faction'])
114  self.vars['defender'] = defender
115  dockeda_ = dict()
116  dockeda_['faction'] = docked_faction
117  self.vars['dockedat'] = dockeda_
118  system = SystemInformation(news_tuple[NewsManager.EVENT_SYSTEM_INDEX])
119  syste_ = dict()
120  syste_['system'] = system.getInfo(system.SYSTEM)
121  syste_['sector'] = system.getInfo(system.SECTOR)
122  self.vars['system'] = syste_
123  for i in range(len(self.item)):
124  self.item[i] = self.translateWord(self.item[i])
125  return string.join(self.item) + self.STARDATE_TEXT + stardate.formatStarDate(self.vars['dockedat']['faction'],self.vars['stardate']['value']) + "\\INDY - Independent Daily Yarn"
126 
127  def formatText(self, text, punc=[' ' , '_' , '.'], capitalise=True):
128  """Runs a quick formatting algorithm over the
129  provided text, using the punc list as a guide to
130  the markup."""
131  for pun in punc:
132  tex = text.split(pun)
133  for i in range(len(tex)):
134  if len(tex[i]) > 1:
135  tex[i] = tex[i][0].capitalize() + tex[i][1:]
136  else:
137  tex[i] = tex[i].capitalize()
138  text = string.join(tex)
139  return text
140 
142  """Each instance of this class acts as an accessor to
143  the faction specific information stored for the purpose
144  of translating news stories."""
145  def __init__(self):
146  import dynamic_news_content
149 
150  def getFactionData(self, faction, variable):
151  """Return the variable information stored for this
152  faction."""
153  if variable in self.faction_dict["alltags"]:
154  try:
155  return self.faction_dict[faction][variable]
156  except:
157  # raise ValueError("Invalid Faction Specified")
158  debug.error("ERROR: FACTION LOOKUP ERROR faction %s variable %s" % (faction, variable))
159  return self.faction_dict['unknown'][variable]
160  else:
161  debug.error("ERROR: VARIABLE LOOKUP ERROR faction %s variable %s" % (faction, variable))
162  return "VARIABLE LOOKUP ERROR"
163 
164  def translateKeyToDictionary(self, variable):
165  """Translates the information from the stored
166  values to those used to lookup items in the item
167  dictionary."""
168  replace = ""
169  if variable == NewsManager.KEYWORD_DEFAULT:
170  replace = "all"
171  elif variable == NewsManager.TYPE_SIEGE:
172  replace = "siege"
173  elif variable == NewsManager.TYPE_EXPLORATION:
174  replace = "exploration"
175  elif variable == NewsManager.TYPE_BATTLE:
176  replace = "battle"
177  elif variable == NewsManager.TYPE_FLEETBATTLE:
178  replace = "fleetbattle"
179  elif variable == NewsManager.TYPE_DESTROYED:
180  replace = "destroyed"
181  elif variable == NewsManager.STAGE_BEGIN:
182  replace = "start"
183  elif variable == NewsManager.STAGE_MIDDLE:
184  replace = "middle"
185  elif variable == NewsManager.STAGE_END:
186  replace = "end"
187  elif variable == NewsManager.SUCCESS_WIN:
188  replace = "success"
189  elif variable == NewsManager.SUCCESS_DRAW:
190  replace = "draw"
191  elif variable == NewsManager.SUCCESS_LOSS:
192  replace = "loss"
193  elif variable == NewsManager.POV_GOOD:
194  replace = "good"
195  elif variable == NewsManager.POV_BAD:
196  replace = "bad"
197  elif variable == NewsManager.POV_NEUTRAL:
198  replace = "neutral"
199  else:
200  raise TypeError("Unrecognised variable")
201  return replace
202 
203  def makeNewsKeyList(self, news_list, news_faction, pov):
204  """Creates a list of the structure used to store
205  each news event."""
206  key_list = list()
207  key_list.append(news_faction)
208  key_list.append(news_list[NewsManager.EVENT_TYPE_INDEX])
209  key_list.append(news_list[NewsManager.EVENT_STAGE_INDEX])
210  key_list.append(self.translateKeyToDictionary(news_list[NewsManager.AGGRESSOR_SUCCESS_INDEX]))
211  key_list.append(self.translateKeyToDictionary(pov))
212  return key_list
213 
214  def getNewsList(self, key_list, get_neutral=False):
215  """Searches the item dictionary to find matching
216  items for this given event."""
217  story_list = self.news_dict
218  try:
219  if get_neutral:
220  key_list[0] = "neutral"
221  for key in key_list:
222  story_list = story_list[key]
223  except:
224  return list()
225  return story_list
226 
227  def getBestMatch(self, stories, varlist):
228  """From the provided list of stories, return the
229  item who's \"scale\" most closely matches that of
230  the given event (minimise variance)."""
231  kw_stories = list()
232  for story in stories:
233  if story[1] == varlist[NewsManager.EVENT_KEYWORD_INDEX]:
234  kw_stories.append(story)
235  if not len(kw_stories):
236  debug.error("ERROR: NO KEYWORD STORIES AVAILABLE FOR "+str(varlist))
237  return False
238  if len(kw_stories) == 1:
239  return kw_stories[0]
240  scale_stories = list()
241  scale_stories.append(kw_stories[0])
242  diff = abs(int(1000*scale_stories[0][0]) - int(1000*varlist[NewsManager.EVENT_SCALE_INDEX]))
243  kw_stories.pop(0)
244  for story in kw_stories:
245  if abs(int(1000*scale_stories[0][0]) - int(1000*varlist[NewsManager.EVENT_SCALE_INDEX])) < diff:
246  scale_stories = list()
247  scale_stories.append(story)
248  elif abs(int(1000*scale_stories[0][0]) - int(1000*varlist[NewsManager.EVENT_SCALE_INDEX])) == diff:
249  scale_stories.append(story)
250  return scale_stories[varlist[NewsManager.RANDOM_INTEGER_INDEX] % len(scale_stories)]
251 
253  """This class is used to manage dynamic news, it is
254  designed to be used as a global object, but can be used
255  otherwise."""
256 
257  RANDOM_INTEGER_INDEX = 0
258  STARDATE_INDEX = 1
259  EVENT_TYPE_INDEX = 2
260  EVENT_STAGE_INDEX = 3
261  AGGRESSOR_INDEX = 4
262  DEFENDER_INDEX = 5
263  AGGRESSOR_SUCCESS_INDEX = 6
264  EVENT_SCALE_INDEX = 7
265  EVENT_SYSTEM_INDEX = 8
266  EVENT_KEYWORD_INDEX = 9
267  AGGRESSOR_FLIGHTGROUP_INDEX = 10
268  AGGRESSOR_SHIPTYPE_INDEX = 11
269  DEFENDER_FLIGHTGROUP_INDEX = 12
270  DEFENDER_SHIPTYPE_INDEX = 13
271 
272  KEYWORD_DEFAULT = "all"
273 
274  TYPE_SIEGE = "siege"
275  TYPE_EXPLORATION = "exploration"
276  TYPE_BATTLE = "battle"
277  TYPE_FLEETBATTLE = "fleetbattle"
278  TYPE_DESTROYED = "destroyed"
279 
280  STAGE_BEGIN = "start"
281  STAGE_MIDDLE = "middle"
282  STAGE_END = "end"
283 
284  SUCCESS_WIN = '1'
285  SUCCESS_DRAW = '0'
286  SUCCESS_LOSS = '-1'
287 
288  POV_GOOD = 5
289  POV_BAD = 6
290  POV_NEUTRAL = 7
291 
292  POV_CUTOFF = 0.25
293 
294  def __init__(self):
295  self.dockedat_faction = None
296  self.updateDockedAtFaction()
299 
300  def translateDynamicString(self, strin):
301  """Takes an argument, of type str (this is not checked),
302  that is of the same format as that stored by
303  self.writeDynamicString(varlist)"""
304  varlist = self.sTovarlist(strin)
305  if varlist[self.AGGRESSOR_FLIGHTGROUP_INDEX] == VS.getPlayer().getFlightgroupName():
306  varlist[self.EVENT_KEYWORD_INDEX] = "player"
307  keys = self.data.makeNewsKeyList(varlist, self.dockedat_faction, self.getPOV(varlist))
308  stories = self.data.getNewsList(keys)
309  if not len(stories):
310  stories = self.data.getNewsList(keys, True)
311  if not len(stories):
312  return False
313  item = self.data.getBestMatch(stories, varlist)
314  if item:
315  return self.translator.translateItem(item, varlist, self.dockedat_faction)
316  else:
317  return False
318 
319  def getPOV(self, varlist):
320  """Returns the corresponding POV_* class variable
321  for the reaction of the dockedat faction to the status
322  of the event."""
323  relatdef = VS.GetRelation(self.dockedat_faction,varlist[self.DEFENDER_INDEX])
324  relatagg = VS.GetRelation(self.dockedat_faction,varlist[self.AGGRESSOR_INDEX])
325  success = varlist[NewsManager.AGGRESSOR_SUCCESS_INDEX]
326  if (relatdef <= -self.POV_CUTOFF and relatagg <= -self.POV_CUTOFF) or (relatdef >= self.POV_CUTOFF and relatagg >= self.POV_CUTOFF):
327  return self.POV_NEUTRAL
328  elif relatdef > relatagg:
329  if success == self.SUCCESS_WIN:
330  return self.POV_BAD
331  elif success == self.SUCCESS_LOSS:
332  return self.POV_GOOD
333  elif success == self.SUCCESS_DRAW:
334  return self.POV_GOOD
335  elif relatdef < relatagg:
336  if success == self.SUCCESS_WIN:
337  return self.POV_GOOD
338  elif success == self.SUCCESS_LOSS:
339  return self.POV_BAD
340  elif success == self.SUCCESS_DRAW:
341  return self.POV_BAD
342  else:
343  debug.debug("ERROR: VS is returning -0 for relationship relatagg number")
344  return self.POV_NEUTRAL
345 
346  def sTovarlist(self, s):
347  """Converts a stored dynamic news string into a
348  variable list usable by other methods and classes."""
349  varlist = s.split(',')
350  varlist[self.RANDOM_INTEGER_INDEX] = int(varlist[self.RANDOM_INTEGER_INDEX])
351  varlist[self.STARDATE_INDEX] = float(varlist[self.STARDATE_INDEX])
352  varlist[self.EVENT_SCALE_INDEX] = float(varlist[self.EVENT_SCALE_INDEX])
353  return varlist
354 
356  """Updates the current self.dockedat_faction to its
357  current value. Should be called before translating
358  a batch of stores."""
359  i = VS.getUnitList()
360  playa=VS.getPlayer()
361  while i.notDone():
362  un = i.current()
363  i.advance()
364  if (un.isDocked(playa) or playa.isDocked(un)):
365  if not (un.isPlanet() or (un.getFactionName() == "neutral")):
366  fac = un.getFactionName()
367  # debug.debug('returning '+un.getName()+' s faction as '+fac+' from flightgroup '+un.getFlightgroupName())
368  self.dockedat_faction = fac
369  break
370  retfac = VS.GetGalaxyFaction(VS.getSystemFile())
371  # debug.debug("Returning " + retfac + " as the systems faction")
372  self.dockedat_faction = retfac
373 
374  def isStoryRelevant(self, strin):
375  """Is the event in this string relevant to the current
376  system and dockedat faction?"""
377  varlist = self.sTovarlist(strin)
378  limit = False
379  if varlist[self.EVENT_TYPE_INDEX] in [self.TYPE_BATTLE, self.TYPE_DESTROYED]:
380  limit = 1
381  else:
382  return True
383  event_sys = varlist[self.EVENT_SYSTEM_INDEX]
384  syslist = [VS.getSystemFile()]
385  done_syslist = list()
386  while limit >= 0:
387  if event_sys in syslist:
388  return True
389  else:
390  done_syslist+=syslist
391  new_syslist = list()
392  for syst in syslist:
393  for i in range(VS.GetNumAdjacentSystems(syst)):
394  sy = VS.GetAdjacentSystem(syst,i)
395  if sy not in done_syslist:
396  new_syslist.append(sy)
397  syslist = new_syslist
398  limit-=1
399  return False
400 
401  def writeDynamicString(self, varlist):
402  """Stores a news story list into the \"dynamic news\"
403  key in the save game."""
404  varlist = string.join([str(vsrandom.randrange(0,4194304))]+varlist,',')
405  import Director
406  Director.pushSaveString(0,"dynamic_news",varlist)
407