-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpractice-5-exceptions-Commissar.py
More file actions
311 lines (274 loc) · 10.3 KB
/
practice-5-exceptions-Commissar.py
File metadata and controls
311 lines (274 loc) · 10.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
# -*- coding: utf-8 -*-
"""
Created on Tue Jul 6 20:00:39 2021
@author: Donald Whitworth
"""
import utils
import json
import math
import time
# Practice problem 1a:
# Remember the try-except block we learned in class?
# Take a look at this division function
def ironDivision(a,b):
if b == 0:
return None
if type(a) != int:
if type(a) != float:
return None
if type(b) != int:
if type(b) != float:
return None
else:
quotient = a/b
return quotient
# Go back into that function and use some if statements to handle the
# following:
# if b is equal to 0, just return "None"
# if a is not an integer or float, just return "None"
# if b is not an integer or float, just return "None"
# Practice problem 1b:
# Let's tackle the same problem in a different way
def lazyDivision(a,b):
try:
quotient = a/b
except:
quotient = None
return quotient
# This time, fix all of the above problems, except do it
# WITHOUT if statements and do it in no more than 5 lines!
# Practice problem 2:
# Last week, I was hard on you with monsterFromFile. This week, we're
# going to finish it out now.
# You should already have the AC and name of the creature down pat.
# HP:
# The HP of the monster is calulated as follows:
# (number of hit dice) * (hit dice average roll + constitution mod)
# The number of hit dice and the constitution mod are in the monster Dict!
# The hit dice type is found in the monster's size. If the monster is:
# Tiny: d4 (average 2.5)
# Small: d6 (average 3.5)
# Medium: d8 (average 4.5)
# Large: d10 (average 6.5)
# Huge: d12 (average 10.5)
# Gargantuan: d20
# Finally, round up if you found something that ends in 0.5
# Attack Bonus:
# Take a look at the "actions" key. It might be an array, it might
# be another dict. Figure out how you're going to handle this!
# Then, once you have a string that has an attack bonus in it,
# Find out how to pick out that number.
# I'd recommend looking into the .find() method for strings
# and knowing how to splice!
# Damage bonus:
# Just like you found the attack bonus, hunt down the damage bonus
# in the same string. It can be found in the open and close parentheses!
# Damage diece:
# Be cautious with this one: it's found next to the damage bonus,
# but be sure you parse the NUMBER of dice and the TYPE of die correctly,
# and be ready to create a utils.Dice() array of all the dice used!
# If you're having trouble, just start with one die instead, and go
# from there.
def monsterFromFile(filename):
monFile = open(filename,"r")
monText = monFile.read()
monDict = json.loads(monText)
monFile.close()
monName = monDict["name"]
ACstring = monDict["otherArmorDesc"].split()
monAC = int(ACstring[0])
monsterHitDice = monDict["hitDice"]
if monDict["size"] == "tiny":
avgRoll = 2.5
elif monDict["size"] == "small":
avgRoll = 3.5
elif monDict["size"] == "medium":
avgRoll = 4.5
elif monDict["size"] == "large":
avgRoll = 5.5
elif monDict["size"] == "huge":
avgRoll = 6.5
elif monDict["size"] == "gargantuan":
avgRoll = 10.5
conPoints = monDict["conPoints"]
conMod = ((conPoints)-10)//2
monsterHP = math.ceil(monsterHitDice*(avgRoll+conMod))
findBonus = monDict["actions"][0]["desc"].find("+")
monAttBonus = int(monDict["actions"][0]["desc"][findBonus+1])
findDamStr = monDict["actions"][0]["desc"].find("(")
findDamStrEnd = monDict["actions"][0]["desc"].find(")")
actStr = monDict["actions"][0]["desc"]
actStrSlice = slice(findDamStr,findDamStrEnd)
damStr = actStr[actStrSlice]
findDamBonus = damStr.find("+")
if findDamBonus == -1:
monDamBonus = 0
else:
monDamBonus = int(damStr[findDamBonus+2])
numDie = int(damStr[1])
monDamDie = utils.Die(int(damStr[3]))
monster = utils.rollingMonster(monsterHP,monDamDie,monDamBonus,monAttBonus,monAC,monName)
return monster
# Practice problem 3:
# We're going to bring it all home:
# write a function called "fightFinal" that will:
# Have a group of monsters fight a second group of monsters.
# Turn order goes as the following:
# First alive group A monster attacks first alive group B monster
# First alive group B monster attacks first alive group A monster
# Second alive group A monster attacks first alive group B monster
# Second alive group B monster attacks first alive group A monster
# Third alive group A monster attacks first alive group B monster
# Third alive group B monster attacks first alive group B monster
# ...
# And so on. If a monster group only has 3 versus 7, then the
# group with more monsters gets to all act before the next round
# starts. So a fighting order with [A1,A2,A3] vs. [B1,B2,B3...B8]
# might look like:
# A1 -> B1
# B1 -> A1
# A2 -> B1 (kills it)
# B2 -> A1
# A3 -> B2
# B3 -> A1
# B4 -> A1 (kills it)
# B5 -> A2
# B6 -> A2
# B7 -> A2
# B8 -> A2
# The monsters are all rolling monsters, of course.
# Also: still print the results of the fight like last assignment,
# now accounting for the groups.
# You should be able to properly read
# Zombie
# Skeleton
# Acolyte
def fightFinal(group1,group2,suspense = False,printing = True):
for monster in group1:
if not monster.alive:
print("you forgot to resfresh")
monster.show()
return
for monster in group2:
if not monster.alive:
print("you forgot to resfresh")
monster.show()
return
tarIndex1 = 0
tarIndex2 = 0
while True:
if suspense:
time.sleep(2)
if printing:
print("Team Deathmatch")
for monster in group1:
monster.show()
for monster in group2:
monster.show()
if len(group1) >= len(group2):
maxLength = len(group1)
else:
maxLength = len(group2)
for i in range(maxLength):
try:
if not group1[tarIndex1].alive:
tarIndex1 += 1
else:
pass
if not group2[tarIndex2].alive:
tarIndex2 += 1
else:
pass
except:
pass
if group1[i].attack() >= group2[tarIndex2].AC:
group2[tarIndex2].damage(group1[i].hit())
if group2[i].attack() >= group1[tarIndex1].AC:
group1[tarIndex1].damage(group2[i].hit())
if not group1[-1].alive or not group2[-1].alive:
break
if not group1[-1].alive or not group2[-1].alive:
break
victor = ""
if group1[-1].alive:
if printing:
print("the victor is", "the first monster group")
for monster in group1:
monster.show()
victor = "First Monster Group"
return "group1"
else:
if printing:
print("the victor is", "the second monster group")
for monster in group2:
monster.show()
victor = "Second Monster Group"
return "group2"
fightFinalAppend = open("fightFinal.txt","a")
fightFinalAppend.write("A fight has just occured\nThe winner is:",victor,"\n")
numMonsters = 0
monNames = []
for monster in group1:
numMonsters += 1
monNames.append(monster.name)
fightFinalAppend.write("The number of monsters in the first group is:",numMonsters,"\nMonsters in the group:",monNames,"\n")
numMonsters = 0
monNames = []
for monster in group2:
numMonsters += 1
monNames.append(monster.name)
fightFinalAppend.write("The number of monsters in the second group is:",numMonsters,"\nMonsters in the group:",monNames,"\n")
if victor == "First Monster Group":
group1HP = 0
for monster in group1:
monster.HP += group1HP
fightFinalAppend.write("Total remaining HP:",group1HP)
else:
group2HP = 0
for monster in group2:
monster.HP += group2HP
fightFinalAppend.write("Total remaining HP:",group2HP)
fightFinalAppend.close()
# Practice problem 4a:
# Have 3 zombies and 3 skeletons fight 6 skeletons.
team1 = []
team2 = []
for i in range(3):
team1.append(monsterFromFile("zombie.monster"))
for i in range(3):
team1.append(monsterFromFile("skeleton.monster"))
for i in range(6):
team2.append(monsterFromFile("skeleton.monster"))
winner = fightFinal(team1,team2,False,False)
print(winner)
# Empirically show who wins if the zombies and skeletons array is
# organized so that the zombies act and are hit first.
# A mathematical argument is not good enough. Use python to prove it.
# (one fight is not enough)
# 4b: do the same for if the skeletons act and are hit first.
# Practice problem 5:
"""
Make an extension to our code to include something we don't have yet!
"""
# Suggestion:
# Note that the "Troll" is a class that exists sort of outside the
# normal generic monster class. That's because the troll is special:
# our code infrastructure isn't really designed to handle all these
# special abilities in a generic rolling monster.
# However, we made the troll regenerate before it attacks
# so that it fits into our fight function.
# (shoot, actually there's a bug where it does it before it hits,
# why don't you go ahead and fix that?)
# Pick any monster that has a special ability like the troll.
# (Hell, even the Zombie's undead fortitude is good enough)
# And make a monster class for it.
# Suggestion:
# Add an initiative system for the monsters
# Suggestion:
# Implement a mechanic of ranged attacks versus melee attacks
# Suggestion:
# Implement ciritical attacks (roll 20 = autohit and double dice)
# alongisde critical fails (roll 1 = miss your attack)
# Or anything else that you wish!
# Submit any relevant changes to known files to me as well.
# For this assignment, it is okay if you change utils.py