Small Python Program for combat in a RPG; help?

Post » Fri Aug 30, 2013 3:51 pm

Hello programming and curious forumers!

I'm trying to write a small program for a boardgame that blends RPG elements. The game is King Arthur & the Knights of the Round Table by Wotan games. I found it for 10 bucks at my local shop. Apparently it was quite popular back in the early/mid 80's, but it was noted for having such an abysmal combat system.

Well I was doing some research and found that there is one revised ruleset for the combat system. It seems straightforward, and although I can do the algorithm in my head, I'm trying to practice my Python programming as much as possible.

No better time than to try writing a program for my new game! (BTW, if anyone ever finds a copy for cheap, I'd totally pick it up! I haven't played it yet, but it's a game where you make/choose your own knight, distribute some stats, and you quest around Britain for honor, estates, and gold to buy new equipment!)

I made a thread before about Python programming, so I know some of you guys are out there, since I had a decent turn out on that thread. I'll go ahead and post the revised rules, and than just layout the algorithm.

THE POINT OF THIS THREAD (for anyone wanting to get straight to the point), is to assist me with my practice of python programming, and making programs that have practicality, and are not simply tutorial exercises, ANNND to spread enthusiasm for coding. :smile:

BTW, I have learned both 2.x AND 3.x. Since I know most Python programmers and hobbyists program with 2.x, I'll go ahead and write my code as such.

---------------------------------------------------------------------------------------------

So the revised combat system for the game is as follows;

"You assign an attack score to each fighter which equals (Own Attack - Enemy Defense) / 10. Then, roll a d10 and add that number to the roll, look up the result on this table:

1 or below: Parried, no damage.
2: Parried, no damage.
3: Light hit, half con loss (-armor)
4. Light hit, half con loss (-armor)
5: Hit, con loss (-armor)
6: Hit, con loss (-armor)
7: Hit, con loss (-armor)
8: Heavy hit, con loss (unmodified by armor)
9: Heavy hit, con loss (unmodified by armor)

10+: Critical hit, con = 3, if lower than 5: Con =0"

So the basic flow variables of the program would be;

ownAttack = raw_input("Enter your own attack!")

enemyDefense = raw_input("Enter the enemy's defense!")

enemyAttack = raw_input("Enter your enemy's attack!")

ownDefense = raw_input("Enter your own defense!")

equals = ownAttack - enemyDefense

From here, I would have to call a random integer between 1 and 10, and then --->

result = equals % random.randint(1, 10) (If I remember correctly, I definitely used that wrong)

And then from here, I am not sure how I would match result with one of the 10 combat results for that turn.

Subsequently, I'd also have to determine what the enemy rolls on me, solve it, and then recall the functions IF no one died/fainted.

DISCLAIMER: Although I'd love to explain a little more about this cool and exciting combat system, I'll save that for afterwards :smile:

Now, I know I didn't format a skeleton. Let me try that now (critique wherever necessary forumers!) I'll go ahead and post this first part!

------------------------------------------

BTW, I've already talked to one mod about this. I'm really digging programming. I'm becoming an advocate slowly for code literacy, even if it's just for enthusiasm and cognitive exercising. I'm having a blast, and I LOVE IT. I'm not pushing it on anyone, but if anyone is interested in anything about coding, please feel free to talk to me (EVEN openly on this thread).

User avatar
Harry Hearing
 
Posts: 3366
Joined: Sun Jul 22, 2007 6:19 am

Post » Fri Aug 30, 2013 8:50 pm

print("Welcome!")print("Prepare yourself for combat!") ownAttack = input(int("Enter your own attack!"))enemyDefense = input(int("Enter your enemy's defense!"))equals = ownAttack - enemyDefense result1 = equals / random.randint(1, 10)  # Fixed DEFRON, I noticed right away something was wrong. Didn't mean for modulus :x if result1 <= 2:  #Nice touch, Reneer, as to not have to waste time rewriting the same output for Result 1 or below    print("Parried, no damage.") elif result1 <= 4:    print("Light hit, half con loss (- armor)") elif result <= 7: # Edited from original format due to major redundancy     print("Hit, con loss (- armor)") elif result1 < 10:    print("Heavy hit, con loss (unmodified by armor)") else: # Fixed for optimal coding!    print("Critical hit, con = 3, if lower than 5: Con = 0")enemyAttack = input(int("Enter your enemy's attack!"))ownDefense = input(int("Enter your own defense!"))equals2 = enemyAttack - ownDefenseresult2 = equals2 / random.randint(1, 10)if result2 <= 2:      print("Parried, no damage.") elif result2 <= 4:    print("Light hit, half con loss (- armor)")elif result2 <= 7:     print("Hit, con loss (- armor)") elif result2 < 10:    print("Heavy hit, con loss (unmodified by armor)") else:     print("Critical hit, con = 3, if lower than 5: Con = 0")print("Your result: " + result)print("Enemy's result: " + result2)

Now here is where I run into my first issue. I'm not sure how to store the potential results for one combat phase in a pythonic manner, and then how to match resultEnemy to one of the choices. Any help guys?

Edit: UPDATE, my code looks so much better already! :D

User avatar
Ashley Tamen
 
Posts: 3477
Joined: Sun Apr 08, 2007 6:17 am

Post » Fri Aug 30, 2013 10:05 am

I'm not familiar with Python, but I think you would do something like this:

intresult = int(result) if result <= 2:  print("Parried, no damage")if result > 2 && result <= 4:  print("Light hit, half con loss (-armor)")
Also, Python is evil because it uses whitespace indentation. :tongue:
User avatar
Horse gal smithe
 
Posts: 3302
Joined: Wed Jul 05, 2006 9:23 pm

Post » Fri Aug 30, 2013 5:42 pm

Hmm! That looks sensible. Let me add that to the skeleton and review it further.

Edit: Which languages do you know?

User avatar
James Rhead
 
Posts: 3474
Joined: Sat Jul 14, 2007 7:32 am

Post » Fri Aug 30, 2013 8:11 pm

Why are you taking the modulus, and why did you not divide by 10 like listed in the formula? I thought you were supposed to divide by 10 and then add the result of the d10 roll. You're not doing that. Instead you're just taking the remainder of ownAttack - enemyDefense divided by a random number between 1 and 10.

Why do you have to store them? Wouldn't just printing out the int be enough?

If you're set on storing them, you can make an array containing all of them. You'd need to do a single if check for it to make sure that the result isn't bigger than 10. Then you'd print the array item at index [resultEnemy - 1]
User avatar
Mashystar
 
Posts: 3460
Joined: Mon Jul 16, 2007 6:35 am

Post » Fri Aug 30, 2013 1:50 pm

C / C++, Java, Visual Basic, and Papyrus. Scripting languages: JavaScript and HTML5. There are probably a few I'm forgetting.

Also, what DEFRON posted regarding arrays would be a good way to go about it too.
User avatar
Christina Trayler
 
Posts: 3434
Joined: Tue Nov 07, 2006 3:27 am

Post » Fri Aug 30, 2013 8:27 pm

Wouldn't be a bad idea to forget Visual Basic :tongue:

Well, your way I think is better in this case, actually. I didn't read the list so I didn't realize there were so many repeats. If each one was unique, I'd go with an array, otherwise if/elseif/else is the better way.

Though don't do distinct if statements. chain them through if/elseif/else as that way once one is triggered, all the others are skipped. With distinct if statements, each one is checked and wastes CPU cycles.
User avatar
Aman Bhattal
 
Posts: 3424
Joined: Sun Dec 17, 2006 12:01 am

Post » Fri Aug 30, 2013 10:40 am

True. The only reason I really know it is because a programming class in high-school used it instead of C++. :(

It's really been years since I touched VB, though I'm sure it's just like riding a broken bicycle. You remember what not to do very quickly. :tongue:
User avatar
steve brewin
 
Posts: 3411
Joined: Thu Jun 21, 2007 7:17 am

Post » Fri Aug 30, 2013 1:25 pm

Hahaha, I learned VisualBasic in HS too. :tongue:

As for the arrays, could you guys explain that further? I'm not entirely following yet.

Edit: As for the actual code for the game, I'll consistently return and edit my second post. Feel free to look back at it :)

User avatar
Kortniie Dumont
 
Posts: 3428
Joined: Wed Jan 10, 2007 7:50 pm

Post » Fri Aug 30, 2013 9:04 am

Yeah. I would have done that too, but Python has this weird elif... thing... that is supposed to be an else if. And I didn't feel like constantly type else if by habit and having to go back and fix it. :tongue:
User avatar
JAY
 
Posts: 3433
Joined: Fri Sep 14, 2007 6:17 am

Post » Fri Aug 30, 2013 9:32 am

given that there were repeats (I didn't realize this since I didn't read them at first -- I know, shame on me), if/elseif/else is the better course (don't do distinct if statements for the reason listed in my last post).

Arrays are basically a collection of data with each item given an index. You can then call that specific item by calling the array at that index number.
User avatar
kennedy
 
Posts: 3299
Joined: Mon Oct 16, 2006 1:53 am

Post » Fri Aug 30, 2013 7:13 pm

In Python, arrays are called http://docs.python.org/2/tutorial/datastructures.html (pretty much).
User avatar
Romy Welsch
 
Posts: 3329
Joined: Wed Apr 25, 2007 10:36 pm

Post » Fri Aug 30, 2013 8:56 pm

Okay, hmm... So how should I arrange these arrays/lists into my code? I am sorry guys, but I'm still not entirely following. ^_^

Also---> What should my else statement return? Something like "Inadequate entry entered" or something like that, yeah? Well I'd want to repeat the function since no acceptable entry was entered.

Let me brush up on how to do that.

User avatar
jason worrell
 
Posts: 3345
Joined: Sat May 19, 2007 12:26 am

Post » Fri Aug 30, 2013 4:36 pm

Your current if/elseif/else is incredibly redundant, not formatted correctly, and would benefit from parenthesis.

You don't need to since there's repeats and so the array would have lots of redundancies. if/elseif/else is better


Your last elif should be your else.

Input checking should happen right after input is taken.
User avatar
John N
 
Posts: 3458
Joined: Sun Aug 26, 2007 5:11 pm

Post » Fri Aug 30, 2013 12:20 pm

I may be rusty, since I haven't done any programming in a few years, but it looks like a lot of those elif statements are redundant.

if result <= 2:

print("Parried, no damage.")

elif result <= 4: #You already know it's not <= 2, because if it was the first if would have caught it

print("Light hit, half con loss (-armor).")

elif result <= 7: #Again, you know it's not <= 2 OR <= 4 because of the previous ifs

print("Hit, con loss (- armor)")

And so on.

Keep in mind I'm assuming your formatting is correct because I can't remember [censored] about Python.

User avatar
Samantha Jane Adams
 
Posts: 3433
Joined: Mon Dec 04, 2006 4:00 pm

Post » Fri Aug 30, 2013 5:57 pm

Let me look it up.

User avatar
Darlene Delk
 
Posts: 3413
Joined: Mon Aug 27, 2007 3:48 am

Post » Sat Aug 31, 2013 12:39 am

Also addressed to DEFRON...


Noted!!

User avatar
Beast Attire
 
Posts: 3456
Joined: Tue Oct 09, 2007 5:33 am

Post » Fri Aug 30, 2013 7:37 pm

As DEFRON noted arrays wouldn't be the best thing to do in this instance, but here is what (I think) it would look like:
responselist = ["Parried, no damage.", "Parried, no damage.", "Parried, no damage.", "Light hit, half con loss (-armor)", "Light hit, half con loss (-armor)", "Hit, con loss (-armor)", "Hit, con loss (-armor)", "Hit, con loss (-armor)", "Heavy hit, con loss (unmodified by armor)", "Heavy hit, con loss (unmodified by armor)", "Critical hit, con = 3, if lower than 5: Con = 0"]print( responselist[int(results)] )
User avatar
Ruben Bernal
 
Posts: 3364
Joined: Sun Nov 18, 2007 5:58 pm

Post » Fri Aug 30, 2013 10:14 am

I'm researching so now, but why are arrays important? And could you also explain how they work? (I'm also looking it up)

ie, print ( responselist[int(results)] )

Edit: Just looked it up. So an array is a list of retrievable information that you build? (I put this into my own words, to see if I understand it, instead of regurgitating precisely what I read online)

User avatar
Anna S
 
Posts: 3408
Joined: Thu Apr 19, 2007 2:13 am

Post » Sat Aug 31, 2013 12:09 am

Arrays, or lists, are important because they represent a list of collected information. Imagine, for example, a list of names. Without a list or array variable type, you would have no real way of searching through the data to find a particular name.

And yes, you can build an array or list at compile time or in runtime. Some languages make it very easy to deal with lists / arrays, while others not so much (imagining having to constantly check to see if the input is out of bounds, etc).
User avatar
Haley Merkley
 
Posts: 3356
Joined: Sat Jan 13, 2007 12:53 pm

Post » Fri Aug 30, 2013 12:29 pm

In this case specifically, you'd be able to just use the roll as an index to look up what to print. So you make that array, save the roll, and do something about the lines of print(responselist[roll]).

User avatar
Rebecca Clare Smith
 
Posts: 3508
Joined: Fri Aug 04, 2006 4:13 pm

Post » Fri Aug 30, 2013 10:37 pm

Pretty much, except arrays (lists) are zero-indexed, so you need to subtract one from results to correct for the offset.

As for validating user input, I don't know what the range of valid results is, but in general its something like

userinput = 0min = 1max = 10while(!(userinput >= min and userinput <= max)):    try:        userinput = int(input("enter a number"))        if(!(userinput >= min and userinput <= max)):            print("number not in valid range, try again")    except ValueError:        print("you did not enter a number")
edit: missing paren

I don't code in python2 any more, above was designed for python3 where raw_input doesn't exist any longer.
User avatar
Alessandra Botham
 
Posts: 3440
Joined: Mon Nov 13, 2006 6:27 pm

Post » Fri Aug 30, 2013 4:37 pm

Also includes Reneer,

Ahh, makes sense now!

[0, 1, 2, 3]

So result would match with the integer, and print the subsequent result. :D

Geniuuuuuus

User avatar
Hannah Whitlock
 
Posts: 3485
Joined: Sat Oct 07, 2006 12:21 am

Post » Fri Aug 30, 2013 1:32 pm

DEFRON

I'm coming back to this later. I'll save this bad boy for later :P

Okay, now it's time to compute the enemy's attack on you. Is there any way to display BOTH your attack roll, and theirs side by side?

What am I saying, of course it is, but we'll have to think through how it works. Let's get to it! ^_^

User avatar
Kara Payne
 
Posts: 3415
Joined: Thu Oct 26, 2006 12:47 am

Post » Fri Aug 30, 2013 7:54 pm

You need to convert that input into integers, otherwise Python will crack the sads about trying to use strings like numbers. I would also chuck a space after the exclamation marks, but that's just aesthetic (can you think why?).

EDIT:
Yeah. It was replace with the completely different "input" :tongue:.
User avatar
Ruben Bernal
 
Posts: 3364
Joined: Sun Nov 18, 2007 5:58 pm

Next

Return to Othor Games