Last active
July 20, 2021 20:11
-
-
Save eddie-knight/357077b8a786851cb8b8bafb37e992d2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import csv | |
## Player Weapons | |
################# | |
# 2h Weapons Note! | |
# two-handed weapons disable usage of the multi-tool (grapple, interact, repair, etc) | |
# Melee weapons are special two-handed weapons that specialize in ship DEFENSE | |
MELEE = "2h_melee" | |
# The pistol is the weapon type that can be equipped by players at all times | |
# low dps, small | |
PISTOL = "pistol" | |
# rifles are somewhat stronger than the pistol | |
# mid to high dps, mid to high range, small | |
RIFLE = "2h_rifle" | |
## Fixed Weapons | |
################ | |
# a REPEATER is a fixed weapon with a small calibre and high rate of fire | |
# mid to low damage, high rate, mid range | |
REPEATER = "repeater" | |
# single-fire rocket launchers sacrifice damage in favor of distance and precision | |
# mid-to-low dps, high range | |
# | |
LAUNCHER = "rocket_launcher" | |
# Cannons balance range and rate of fire while achieving a high damage output | |
# high dps, mid range | |
CANNON = "cannon" | |
# HEAVY CANNONs have a high range and accuracy while sacrificing rate of fire | |
# high damage, high range, low rate | |
HEAVY = "heavy_cannon" | |
# Barrage rocket launchers sacrifice distance and precision in favor of high damage and/or rate of fire | |
# high dps, mid-to-low range, medium or large | |
BARRAGE = "barrage_rockets" | |
# point defense cannons will automatically fire at incoming rockets, disabling them if a successful hit is landed | |
# point DEFENSE weapons may look small, but the clear area on all sides requires them to be medium or large weapons | |
# low dps, mid-to-low range | |
DEFENSE = "point_defense" | |
# pulse weapons are weapons with a wider than normal area of attack, but short range | |
# any dps, low range, medium or large | |
PULSE = "pulse_weapon" | |
## Sizes | |
sm = "small" | |
md = "medium" | |
lg = "large" | |
co = "colossal" | |
# some value combinations may not be useful for our purposes | |
skipped = "skipped" | |
unhandled = "unhandled" | |
class StatBlock: | |
def __init__(self, dmg, rate, accuracy, eff): | |
self.damage = dmg | |
self.rate = rate | |
self.accuracy = accuracy | |
self.efficiency = eff | |
self.size = None | |
self.items = [self.damage, | |
self.rate, | |
self.accuracy, | |
self.efficiency] | |
self.value = sum(self.items) | |
self.prepare() | |
def small(self): | |
return self.value == 10 | |
def medium(self): | |
return self.value == 15 | |
def large(self): | |
return self.value == 20 | |
def colossal(self): | |
return self.value == 25 | |
def prepare(self): | |
if not self.small() and self.efficiency > self.damage + self.rate + self.accuracy: | |
return | |
if self.small(): | |
self.size = sm | |
elif self.medium(): | |
self.size = md | |
elif self.large(): | |
self.size = lg | |
elif self.colossal(): | |
self.size = co | |
else: | |
return | |
self.weapon_class = self.get_weapon_class() | |
self.items.append(self.size) | |
def high(self, value): | |
if self.small() and value >= 5: | |
return True | |
if self.medium() and value >= 6: | |
return True | |
if (self.large() or self.colossal()) and value >= 8: | |
return True | |
return False | |
def mid(self, value): | |
if self.small() and (value == 3 or value == 4): | |
return True | |
if self.medium() and (value == 4 or value == 5): | |
return True | |
if (self.large() or self.colossal()) and (value >= 5 and value <= 8): | |
return True | |
return False | |
def low(self, value): | |
if self.small() and value < 3: | |
return True | |
if self.medium() and value < 4: | |
return True | |
if (self.large() or self.colossal()) and value < 5: | |
return True | |
return False | |
def get_values(self): | |
return (self.damage, self.rate, self.accuracy, self.efficiency) | |
def get_weapon_class(self): | |
damage, rate, accuracy, efficiency = self.get_values() | |
if accuracy == 1: | |
if self.small() and not self.mid(damage+rate): | |
return MELEE | |
return skipped | |
if self.small(): # small may be range=2: lowest accuracy | |
if self.low(damage+rate) \ | |
or (self.low(accuracy) and (self.low(damage) or self.low(rate))): | |
return PISTOL # low DPS -OR- low damage/rate and low range | |
if not self.low(damage+rate) and not self.low(accuracy): | |
return RIFLE | |
return CANNON | |
if accuracy == 2: # med or large range=2 are point DEFENSE: low distance | |
if not self.colossal(): | |
return DEFENSE | |
return skipped # no colossal point DEFENSE weapons | |
if self.low(damage) and self.low(accuracy) and self.low(rate): | |
return skipped # anything weak left by this point should be dropped | |
if self.low(accuracy): | |
if self.high(rate): | |
return BARRAGE | |
if self.high(damage): | |
return PULSE | |
return skipped | |
if self.mid(accuracy) and not self.low(damage): | |
if self.high(rate): | |
return REPEATER | |
if self.high(damage) and self.low(rate): | |
return CANNON | |
if self.high(accuracy): | |
if self.low(rate) and self.low(damage): | |
return LAUNCHER | |
if self.high(damage) and self.low(rate): | |
return HEAVY | |
return skipped | |
return unhandled | |
def entries(): | |
# tite_row = ["damage", "rate", "range", "cost efficiency", "type", "size"] | |
data = { | |
MELEE: [], | |
PISTOL: [], | |
RIFLE: [], | |
REPEATER: [], | |
CANNON: [], | |
HEAVY: [], | |
LAUNCHER: [], | |
BARRAGE: [], | |
DEFENSE: [], | |
PULSE: [], | |
skipped: [], | |
unhandled: [], | |
} | |
i = 0 | |
for dmg in list(range(1, 11)): | |
for rate in list(range(1, 11)): | |
for rng in list(range(1, 11)): | |
for eff in list(range(1, 11)): | |
entry = StatBlock(dmg, rate, rng, eff) | |
if entry.size: | |
data[entry.weapon_class].append(entry.items) | |
if entry.weapon_class is not skipped \ | |
and entry.weapon_class is not unhandled: | |
i += 1 | |
del data[skipped] | |
del data[unhandled] | |
return data, i | |
def sort_data(data): | |
tree = [] | |
for value in list(range(1,11)): | |
for entry in data: | |
if entry[3] == value: | |
tree.append(entry) | |
return tree | |
def write_data(data, size): | |
with open(f'{size}.csv', 'w', newline='') as f: | |
writer = csv.writer(f) | |
writer.writerows(data) | |
def main(): | |
data, count = entries() | |
for category in data: | |
sorted_data = sort_data(data[category]) | |
print(f"Entries for {category}: {len(sorted_data)}") | |
write_data(sorted_data, category) | |
print(f"Entries in Knowledge Tree: {count}") | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment