diff --git a/airpower/aircraft.py b/airpower/aircraft.py index d2739bb7..6b208d76 100644 --- a/airpower/aircraft.py +++ b/airpower/aircraft.py @@ -1,6 +1,7 @@ import airpower.aircrafttype as apaircrafttype import airpower.altitude as apaltitude import airpower.azimuth as apazimuth +import airpower.data as apdata import airpower.draw as apdraw import airpower.hex as aphex import airpower.hexcode as aphexcode @@ -35,6 +36,8 @@ def __init__(self, name, aircrafttype, hexcode, azimuth, altitude, speed, config self._configuration = configuration self._flighttype = "LVL" self._powersetting = "N" + self._turnfp = 0 + self._bank = None self._fpcarry = 0 self._apcarry = 0 self._aircrafttype = apaircrafttype.aircrafttype(aircrafttype) @@ -235,7 +238,7 @@ def _S(self, spbrfp): self._spbrap = -spbrfp / 0.5 - def _TD(self, turndirection, turnrate): + def _TD(self, bank, turnrate): """ Start a turn in the specified direction and rate. @@ -243,7 +246,7 @@ def _TD(self, turndirection, turnrate): turnrates = ["EZ", "TT", "HT", "BT", "ET"] assert turnrate in turnrates - self._turndirection = turndirection + self._bank = bank self._turnrate = turnrate def _TL(self, facingchange): @@ -252,9 +255,17 @@ def _TL(self, facingchange): Turn left. """ - if self._turnrate == None: - # Implicitly declare a turn rate of EZ. - self._TD("L", "EZ") + if self._bank == "R": + self._turnfp -= 1 + minturnrate = apdata.determineturnrate(self._altitudeband, self._speed, self._turnfp, facingchange) + if minturnrate == None: + raise ValueError("attempt to turn faster than the maximum turn rate.") + + self._turnfp = 0 + self._bank = "L" + + # Implicitly declare turn rates. + self._turnrate = minturnrate if self._maxturnrate == None: self._maxturnrate = self._turnrate @@ -288,9 +299,17 @@ def _TR(self, facingchange): Turn right. """ - if self._turnrate == None: - # Implicitly declare a turn rate of EZ. - self._TD("L", "EZ") + if self._bank == "L": + self._turnfp -= 1 + minturnrate = apdata.determineturnrate(self._altitudeband, self._speed, self._turnfp, facingchange) + if minturnrate == None: + raise ValueError("attempt to turn faster than the maximum turn rate.") + + self._turnfp = 0 + self._bank = "R" + + # Implicitly declare turn rates. + self._turnrate = minturnrate if self._maxturnrate == None: self._maxturnrate = self._turnrate @@ -421,6 +440,8 @@ def _doaction(self, action): self._vfp += 1 else: raise ValueError("action %s does not begin with H, D, or C." % action) + + self._turnfp += 1 lastx = self._x lasty = self._y diff --git a/airpower/data.py b/airpower/data.py new file mode 100644 index 00000000..0b36062f --- /dev/null +++ b/airpower/data.py @@ -0,0 +1,77 @@ +def turnrequirement(altitudeband, speed, rate): + + """ + Determine the turn requirement accoring to the Air Power Integrated Turn + Charts. + """ + + speed = int(speed) + if speed < 8: + ispeed = speed - 1 + elif speed < 10: + ispeed = 7 + elif speed < 12: + ispeed = 8 + elif speed < 14: + ispeed = 9 + else: + ispeed = 10 + + irate = ["EZ", "TT", "HT", "BT", "ET"].index(rate) + + if altitudeband == "LO" or altitudeband == "ML": + raw = [ + [ 60, 1, 2, 3, 4, 6, 8, 10, 12, 14, 16, 20, ], + [ 90, 60, 1, 2, 3, 4, 5, 6, 8, 19, 12, 14, ], + [ 0, 90, 60, 1, 2, 2, 3, 4, 6, 8, 10, 12, ], + [ 0, 0, 90, 60, 1, 1, 2, 3, 4, 6, 8, 10, ], + [ 0, 0, 0, 60, 60, 1, 1, 2, 3, 4, 6, 8, ], + ][irate][ispeed] + elif altitudeband == "MH": + raw = [ + [ 1, 2, 3, 4, 6, 8, 10, 12, 14, 16, 18, 22, ], + [ 60, 1, 2, 3, 4, 6, 7, 8, 10, 12, 14, 18, ], + [ 0, 60, 1, 2, 3, 4, 5, 6, 8, 10, 12, 14, ], + [ 0, 0, 60, 1, 2, 2, 3, 4, 6, 7, 10, 11, ], + [ 0, 0, 0, 60, 1, 1, 2, 2, 4, 5, 7, 9, ], + ][irate][ispeed] + elif altitudeband == "HI": + raw = [ + [ 2, 3, 4, 6, 8, 10, 12, 14, 16, 18, 20, 24, ], + [ 1, 2, 3, 4, 5, 6, 8, 10, 12, 14, 16, 20, ], + [ 0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 13, 16, ], + [ 0, 0, 1, 2, 3, 3, 4, 6, 7, 8, 10, 12, ], + [ 0, 0, 0, 1, 2, 2, 3, 4, 5, 6, 8, 10, ], + ][irate][ispeed] + elif altitudeband == "EH" or "UH": + raw = [ + [ 3, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 28, ], + [ 0, 4, 6, 8, 10, 12, 13, 14, 16, 18, 21, 24, ], + [ 0, 0, 4, 6, 7, 8, 10, 11, 13, 15, 18, 21, ], + [ 0, 0, 0, 4, 5, 6, 7, 8, 10, 12, 14, 18, ], + [ 0, 0, 0, 0, 4, 5, 6, 7, 9, 10, 12, 14, ], + ][irate][ispeed] + if altitudebane == "UH" and raw != 0: + raw += 2 + + if raw == 0: + return None + else: + return raw + +def determineturnrate(altitudeband, speed, fp, facingchange): + + """ + Return the minimum turn rate capable of a turn of the given facing change + after expending the given number of FPs. If no turn rate is capable, return + None. + """ + + for rate in ["EZ", "TT", "HT", "BT", "ET"]: + requirement = turnrequirement(altitudeband, speed, rate) + if requirement == None: + return None + if facingchange > 30 and facingchange <= requirement: + return rate + if fp >= requirement: + return rate