Package schlachtfeld :: Module Char
[hide private]
[frames] | no frames]

Source Code for Module schlachtfeld.Char

  1  #!/bin/env python 
  2  # -*- coding: utf-8 -*- 
  3   
  4  # Schlachtfeld - Großk�mpfe im EWS System  
  5  #   http://rpg-tools-1d6.sf.net 
  6  # Copyright © 2007 - 2007 Achim Zien 
  7   
  8  # This program is free software; you can redistribute it and/or modify 
  9  # it under the terms of the GNU General Public License as published by 
 10  # the Free Software Foundation; either version 2 of the License, or 
 11  # (at your option) any later version. 
 12   
 13  # This program is distributed in the hope that it will be useful, 
 14  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 15  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 16  # GNU General Public License for more details. 
 17   
 18  # You should have received a copy of the GNU General Public License 
 19  # along with this program; if not, write to the Free Software 
 20  # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, 
 21  # MA 02110-1301 USA 
 22   
 23   
 24  ''' 
 25  Characters and methods for use in schlachtfeld module. 
 26  Characters act on their own now and can be imported and saved via amov module. 
 27  ''' 
 28   
 29   
 30  #### IMPORTS #### 
 31   
 32  # for the fighting 
 33  from random import randrange as rnd 
 34  from random import shuffle 
 35  import math 
 36  # For selection of armies through command line arguments:  
 37  import sys 
 38  # EWS standard dice 
 39  from ews import pmw6 
 40  # Name-Generator 
 41  import namen 
 42  # Obtain Charakters from yaml-files 
 43  from amov import Charakter, Versionsverwaltung 
 44  # replaced the alias with the real directory.  
 45   
 46  #### IMPORTS #### 
 47   
 48   
 49   
 50   
 51  #### Top-Level Objects #### 
 52   
 53  name_objekt = namen.Name() 
 54   
 55  # style configurations: skill mod, win own damage, loose own damage, win enemy damage, loose enemy damage, special pars 
 56  # damage code: (base damage, result stepsize); stepsize 0 means None 
 57  default_style = (0,(3,3),(3,3),(3,3),(3,3),None) 
 58  defensive_style = (-3,(0,0),(0,3),(3,3),(3,3),None) 
 59  offensive_style = (6,(3,3),(0,0),(3,3),(3,3),'dead') 
 60  escape_style = (6,(3,3),(3,3),(0,0),(0,0),'escape') 
 61  styledict = {'defensive':defensive_style, 'offensive':offensive_style, 'default':default_style, 'escape':escape_style} 
 62   
 63  atscatter = [3,2,1] 
 64  #### Top-Level Objects #### 
 65   
 66   
 67   
 68   
 69  #### WRAPPERS #### 
 70   
71 -def ews():
72 """Do one roll with the plusminus d6 die (wrapper for a function in pmw6).""" 73 return pmw6.pmw6()
74
75 -def check(skill,MW):
76 """Check if a given skill test reached a min-value (wrapper for a function in pmw6).""" 77 return pmw6.check(skill,MW)
78
79 -def ocheck(skill,MW):
80 """Return the degree of success / failure for a skill check (wrapper for a function in pmw6).""" 81 return pmw6.ocheck(skill,MW)
82
83 -def name_it(language="Esperanto"):
84 '''Return a name corresponding to the characters language.''' 85 return name_objekt.erzeuge(language)
86 87 #### WRAPPERS #### 88 89 90 91 92 #### CLASSES #### 93
94 -class Char:
95 """A single soldier. Will be imported from either a prefab character file from amov or via a template."""
96 - def __init__(self,source="tag:1w6.org,2007:Mensch",template=True):
97 '''Basic creation of a single soldier.''' 98 # creation from amov template/char 99 self.source = source 100 self.ID = Versionsverwaltung.Versionen(self.source, u"Vorlagen").neuste 101 self.amov = Charakter.Charakter(self.ID) 102 103 # rank 104 self.name = name_it() 105 self.chartype = 'Soldat' 106 self.description = self.amov.beschreibung 107 self.sprache = self.amov.sprache 108 109 # amov combat values 110 #: The damage a character can take before going down. 111 self.bTP = self.amov.kampfwerte['Trefferpunkte'] 112 #: The wound value determines, how much damage suffices to inflict a wound on the character. It's a List containing the value for deep wounds and for critical wounds. A deep wounds weakens the character (3 points off any skill and attribute), a critical wounds disables (the character has to roll, if he keeps standing). 113 self.WS = [self.amov.kampfwerte['Wundschwelle'],self.amov.kampfwerte['Wundschwelle'] * 3] 114 #: The damage which te characters main weapon inflicts. 115 self.dam = self.amov.kampfwerte['Hauptwaffe']['Waffe']['Schaden'] 116 #: The attack value of the character. 117 self.attack = self.amov.kampfwerte['Hauptwaffe']['Kampffertigkeit']['Zahlenwert'] 118 #self.skill = self.amov.kampfwerte['Hauptwaffe']['Kampffertigkeit']['Name'] 119 #: The armor value of the character. 120 self.armor = self.amov.schutz 121 122 # variable schlachtfeld values 123 self.TP = self.bTP 124 self.wounds = [0,0] #: deep wounds, critical wounds 125 self.morale = [12,0,0,0,0] #: base, speech, combat, bias, hero 126 self.exp = 0 127 self.style = default_style 128 129 # even template-soldiers are not all equal 130 if template: 131 self.morale[0] += rnd(-3,4) 132 for i in atscatter: 133 self.attack += rnd(-i,i+1) 134 135 # schlachtfeld organization values 136 self.active = True 137 self.alive = True 138 self.fled = False 139 self.queue = 0 140 self.host = None # ToDo: Add Host! Blocker! 141 142 return
143 144
145 - def __repr__(self):
146 ''' Hopefully nice printout for a soldier.''' 147 if self.name != None: 148 scribble = 'Name: ' + self.name 149 else: 150 scribble = "Unknown Char" 151 scribble += '\nTP: ' + `self.TP` 152 scribble += '\nWunden: ' + `self.wounds` 153 scribble += '\nAktiv: ' + `self.alive` 154 scribble += '\nAngriff: ' + `self.attack` + ', Exp: ' + `self.exp` 155 scribble += '\nAktuelle Moral: ' + `self.morale` 156 scribble += '\nArt: ' + self.chartype 157 scribble += '\nSprache: ' + self.sprache 158 if self.host: 159 scribble += '\nBatallion: ' + self.host.name 160 return scribble
161 162
163 - def sethost(self, host):
164 '''Assign the soldier to a hosting Group-Entity.''' 165 self.host = host 166 return
167 168
169 - def name_me(self,template):
170 '''Give the soldier a random name or import it from the file.''' 171 if template: 172 self.nametype = self.amov.grunddaten['Herkunft']['Sprache'] 173 self.name = name_it(self.nametype) 174 else: 175 self.name = self.amov.name 176 return
177 178
179 - def damage(self, tp, ws, hws):
180 '''Damage a character and check for suvivial. Arguments: hitpoints, wounds heavy wounds.''' 181 self.TP -= tp + (ws * self.WS[0]) + (hws * self.WS[1]) # self.WS is a list containing the wound value and the heavy wound value of the character. 182 self.wounds[0] += ws 183 self.wounds[1] += hws 184 self.morale[2] -= ws + 3*hws 185 self.checkalive() 186 return
187 188
189 - def checkalive(self):
190 '''Check if a character is still alive after being damaged.''' 191 morale = sum(self.morale) 192 self.alive = (self.TP > min(0,15-morale)) and (self.wounds[1] < max(2,morale/6)) and (self.wounds[0] < max(5,morale/3)) 193 if not self.alive: 194 self.host.active.remove(self) 195 return
196 197
198 - def checkmorale(self):
199 ''' 200 A morale-check to figure out if the character will cross over or desert his Group. 201 This method also automatically determines the fighting style of the soldier. 202 ''' 203 MW = sum(self.host.situation) 204 res = ocheck(sum(self.morale),MW) 205 host = self.host 206 if res < -10 and self.host.enemy: 207 self.host.active.remove(self) 208 self.sethost(host.enemy) 209 self.host.active.append(self) 210 self.morale[2] = 0 211 elif res < -3: 212 self.style = escape_style 213 elif res < 0: 214 self.style = defensive_style 215 elif res < 5: 216 self.style = default_style 217 else: 218 self.style = offensive_style 219 self.morale[4] = 0 # reset of hero-added morale 220 return
221 222
223 - def escape_check(self):
224 '''Check if the character tried to escape and made it alive.''' 225 if self.style == escape_style and self.active and self.alive: 226 self.host.active.remove(self) 227 self.sethost(None) 228 self.fled = True 229 return
230 231
232 - def queue_up(self,amt=-1):
233 '''Adjust queue-value of character - either reduce by 1 (standard) or raise or lower deliberately. Check for activeness.''' 234 self.queue += amt 235 if amt > 0: 236 self.host.active.remove(self) 237 if self.queue > 0: 238 self.active = False 239 else: 240 self.active = True 241 self.host.active.append(self) 242 return
243 244
245 - def attack(self):
246 ''' 247 Make an attack-roll to be compared to the enemy's roll. Base method to evaluate comabat. 248 Contributions: base skill, weapon, armor, +-d6, wounds (deep: each -3, crit: each -6 while in combat), , group situation (strategy & bias), morale bonus 249 ''' 250 tmp = self.attack + self.dam + self.armor + ews() - 3*(self.wounds[0]+2*self.wounds[1]) + self.host.situation[2] - self.host.situation[1] + max(0, (12-sum(self.morale))/3) 251 return tmp
252 253
254 - def upgrade(self,expadd,object=('random',0)):
255 ''' 256 Randomly enhance the characters skills and attributes. Dashes are spent and collected until a higher level is reached. Higher attributes and skills are preferred, thus specializing the character. 257 expadd: number of dashes (float - subdashes included) 258 object: object of enhancement; 'attribute', 'skill' or 'random' + name of object; standard is 'random' 259 ''' 260 return
261 262
263 - def manual_sytle(self, style):
264 self.style = styledict[style] 265 return
266 267 268 269
270 -class Leader(Char):
271 """A leader of an Army or group. Can emerge from Char()."""
272 - def __init__(self,source="default",template=True):
273 # additionally import important skills 274 if 'Strategie' in self.amov.fertigkeiten: 275 self.strategy_skill = self.amov.fertigkeiten['Strategie']['Zahlenwert'] 276 else: 277 self.strategy_skill = 9 278 279 if 'Taktik' in self.amov.fertigkeiten: 280 self.tactics_skill = self.amov.fertigkeiten['Taktik']['Zahlenwert'] 281 else: 282 self.tactics_skill = 9 283 284 if 'Rede' in self.amov.fertigkeiten: 285 self.speech_skill = self.amov.fertigkeiten['Rede']['Zahlenwert'] 286 else: 287 self.speech_skill = 9 288 289 self.chartype = 'Anführer' 290 return
291 292
293 - def __repr__(self):
294 '''Print-out modification for leaders.''' 295 scribble = Char.__repr__(self) 296 scribble += '\nStrategie-Fertigkeit: ' + self.strategy_skill 297 scribble += '\nTaktik-Fertigkeit: ' + self.tactics_skill 298 scribble += '\nRede-Fertigkeit: ' + self.speech_skill 299 return scribble
300 301
302 - def speak(self):
303 '''Speak to raise or lower morale of soldiers in his group.''' 304 bonus = max(ocheck(self.speech_skill, sum(self.host.situation)) / 3, -6) # capping @ -6 malus 305 for i in self.host.active: 306 if i.morale[1] < self.speech_skill/3: 307 i.morale[1] += bonus 308 return
309 310
311 - def plan(self):
312 '''Make strategical or tactical considerations to raise or lower attack score of soldiers.''' 313 tmp = self.host.grouptype 314 if tmp == "Armee": 315 skill = self.strategy_skill 316 elif tmp =="Gruppe": 317 skill = self.tactics_skill 318 bonus = ocheck(skill, sum(self.host.situation)) / 3 319 self.host.situation[2] = bonus 320 return
321 322 323
324 -class Hero(Char):
325 """A battle hero. Might be external or emerging from Char() during battle."""
326 - def __init__(self,host=None,exp=3,weap=4,arm=2,base_tp=24,base_attack=12,morale=18,source=u"tag:1w6.org,2007:Mensch"):
327 Char.__init__(self,host,exp,weap,arm,base_tp,base_attack,morale) 328 self.chartype = 'Held' 329 return
330
331 - def checkmorale(self):
332 '''Heroes hail their masters, no morale check!''' 333 MW = sum(self.host.situation) 334 res = ocheck(sum(self.morale),MW) 335 if res < 0: 336 self.style = defensive_style 337 elif res < 5: 338 self.style = default_style 339 else: 340 self.style = offensive_style 341 self.morale[4] = 0 # reset of hero-added morale 342 return
343
344 - def motivate(self):
345 '''Heroes motivate the surrounding fighters.''' 346 for i in self.host.active: 347 i.morale[4] += self.morale[2] 348 self.host.situation[3] += 1 349 return
350 351 352 #### CLASSES #### 353