Advertisement
Guest User

kirov

a guest
Jun 29th, 2008
71
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 13.83 KB | None | 0 0
  1. #axis and allies battle simulator program
  2. #prefix definitions: a = attacker, d = defender, o = original
  3. #
  4. #  
  5. #this version uses/supports:
  6. #'sub insta kills' rule
  7. #'two hit battleships' rule - bug: subs can still kill batts in 1 hit
  8. #battleship bombardment
  9. #
  10. #
  11. #add proper error handling
  12. #add optional 'type of mission' options
  13. #
  14. #
  15. #Planning/Notes:
  16. #
  17. #TYPES OF 'MISSIONS'
  18. #unit arrangement for above scenario (lose left units first):
  19. #if conditions for missions not met, default to weakest/(cheapest?) die first
  20. #
  21. #1. Occupy enemy territory at all costs (attacker only)
  22. #if tank > 0:
  23. #inf, fight, bomb, *ships here, order doesn't matter*
  24. #elif inf > 0:
  25. #tank, fight, bomb, inf, *ships here*
  26. #else:
  27. #weakest die first
  28. #
  29. #2. Protect [x unit] at all costs
  30.  
  31. #############################################################################################
  32. #                                                                                           #
  33. #   FOR THOSE NOT FAMILIAR WITH THE BOARD GAME 'AXIS & ALLIES':                             #
  34. #                                                                                           #
  35. #    -1- AA is similar to Risk but there are different units which have different           #
  36. #   attack and defense skills                                                               #
  37. #    -2- 'two hit battleship' means battleships can take 2 hits before being destroyed.     #
  38. #   they still only fire one shot each, like the other units                                #
  39. #    -3- 'sub insta kills' means victims of attacking submarines cannot fire back           #
  40. #   and are destroyed immediately (unless the victim is a two hit battleship, in which      #
  41. #   case it simply gets damaged and IS allowed to return fire)                              #
  42. #    -4- antiaircraft guns (AA guns) can only fire at the beginning of a battle             #
  43. #    -5- only the defender can have an AA gun, and only one may exist at one time           #
  44. #    -6- 'bombarding battleships' only fire once, and are only supposed to be usable        #
  45. #   against land targets (as opposed to sea). only attackers can bombard                    #
  46. #                                                                                           #
  47. #    This information is presented as it's relevant to this program. Not all of this info   #
  48. #    is directly translatable to the actual board game                                      #
  49. #############################################################################################
  50.  
  51. import random
  52.  
  53. class mainClass():
  54.     def army_chooser(self, team):
  55.         inf = 0; tank = 0; fight = 0; bomb = 0; trans = 0; dummy_unit = 0
  56.         sub = 0; carr = 0; batt = 0; battb = 0; dbatt = 0; army_ready = 0; aa_gun = 0
  57.         while army_ready != 1:
  58.             print "\nEnter 0 when all %s units have been entered\n" % team
  59.             print 'Current %s force:' % team
  60.             print inf, 'Infantry'
  61.             print tank, 'Tank(s)'
  62.             print fight, 'Fighter(s)'
  63.             print bomb, 'Bomber(s)'
  64.             print trans, 'Transport(s)'
  65.             print sub, 'Submarine(s)'
  66.             print carr, 'Carrier(s)'
  67.             print batt / 2, 'Battleship(s)'
  68.             if team == 'defending':
  69.                 print aa_gun, 'AA gun(s)'
  70.             else:
  71.                 print battb, 'Bombarding battleships'
  72.             print '\n1. Infantry\n2. Tank\n3. Fighter\n4. Bomber\n5. Transport\n6. Submarine'
  73.             print '7. Carrier\n8. Battleship'
  74.             if team == 'defending':
  75.                 print '9. AA Gun'
  76.             else:
  77.                 print '9. Bombarding battleship'
  78.             try:
  79.                 choice = input('\nEnter the number to add a type of unit')
  80.                 if choice == 0:
  81.                     army_ready = 1
  82.                 elif choice == 1:
  83.                     inf = input('How many?')
  84.                 elif choice == 2:
  85.                     tank = input('How many?')
  86.                 elif choice == 3:
  87.                     fight = input('How many?')
  88.                 elif choice == 4:
  89.                     bomb = input('How many?')
  90.                 elif choice == 5:
  91.                     trans = input('How many?')
  92.                 elif choice == 6:
  93.                     sub = input('How many?')
  94.                 elif choice == 7:
  95.                     carr = input('How many?')
  96.                 elif choice == 8:
  97.                     batt = input('How many?') * 2
  98.                 elif (choice == 9) and (team == 'attacking'):
  99.                     battb = input('How many?')
  100.                 elif (choice == 9) and (team == 'defending'):
  101.                     aa_gun = 1
  102.             except:
  103.                 print 'Invalid input'
  104.         #numbers after unit names are their attack and defense skills, respectively
  105.         #some units, like battb, are an exception
  106.         return [trans, 0, 1, 'trans'], [inf, 1, 2, 'inf'], [tank, 3, 2, 'tank'],\
  107.                [fight, 3, 4, 'fight'], [bomb, 4, 1, 'bomb'], [sub, 2, 2, 'sub'],\
  108.                [carr, 1, 3, 'carr'], [batt, 4, 4, 'batt'],\
  109.                [battb, 0, 0, 'battb'], [dbatt, 4, 4, 'dbatt'],\
  110.                [aa_gun, 0, 0, 'aa'], [dummy_unit, 0, 0, 'dummy']
  111.  
  112.     def duplicate_original_armies(self, o_a_units, o_d_units):
  113.         a_units = []; d_units = []
  114.         for i in o_a_units:
  115.             a_units.append(i[:])
  116.         for i in o_d_units:
  117.             d_units.append(i[:])
  118.         return a_units, d_units
  119.  
  120.     def roll(self, units, stance, team, a_units, d_units):
  121.         hits = 0; sub_insta_kills = 0; d_sub_hits = 0; batt_present = 0
  122.         for i in units:
  123.             if i[0] > 0:        #i[0] is amount of a specific unit
  124.                 skill = i[stance]       #chooses attacker or defender fighting skill
  125.                 if i[3] == 'batt':   #if battleship
  126.                     units[7][0] = units[7][0] / 2  #each 2 hit battleship only takes one shot each
  127.                     batt_present = 1
  128.                 for j in range(i[0]):       #roll one die per unit present
  129.                     if random.randint(1, 6) <= skill:
  130.                         if (i[3] == 'sub') and (team == 'a'):
  131.                             sub_insta_kills += 1
  132.                         elif (i[3] == 'sub') and (team == 'd'):
  133.                             d_sub_hits += 1
  134.                         else:
  135.                             hits += 1
  136.         if batt_present == 1:
  137.             units[7][0] = units[7][0] * 2 #restore original battleship value
  138.         return [hits], sub_insta_kills, d_sub_hits
  139.  
  140.     def remove_casualties(self, units, opposing_hits, d_sub_hits):
  141.         passer = 0
  142.         for i in units:
  143.             while (i[0] > 0) and ((opposing_hits > 0) or (d_sub_hits > 0)):
  144.                 if i[3] == 'batt':
  145.                     while (opposing_hits > 0) and (i[0] > 0):
  146.                         i[0] = i[0] - 2 #battleship - 2
  147.                         opposing_hits = opposing_hits - 1
  148.                         units[9][0] += 1 #dbatt + 1
  149.                     while (d_sub_hits > 0) and (i[0] > 0):
  150.                         i[0] = i[0] - 2
  151.                         d_sub_hits = d_sub_hits - 1
  152.                         units[9][0] += 1 #dbatt + 1  
  153.                 elif (i[3] == 'fight') or (i[3] == 'bomb'):
  154.                     passer += 1
  155.                     while (opposing_hits > 0) and (i[0] > 0):
  156.                         i[0] = i[0] - 1
  157.                         opposing_hits = opposing_hits - 1
  158.                 elif i[3] == 'dummy':
  159.                     d_sub_hits = 0
  160.                 if ((i[3] != 'batt') and (i[3] != 'fight')) and ((i[3] != 'bomb') and (i[3] != 'dummy')) and\
  161.                    (i[3] != 'battb'):
  162.                     while ((opposing_hits > 0) or (d_sub_hits > 0)) and (i[0] > 0):
  163.                         i[0] = i[0] - 1
  164.                         opposing_hits = opposing_hits - 1
  165.                 if passer >= 3:
  166.                     d_sub_hits = 0
  167.         return units
  168.  
  169.     def fire_aa_and_remove_aa_casualties(self, aa_gun, a_units):
  170.         planes = 0; aa_hits = 0
  171.         if aa_gun == 1:
  172.             for i in a_units:
  173.                 if (i[3] == 'fight') or (i[3] == 'bomb'):
  174.                     planes += i[0]
  175.             for j in range(planes):
  176.                 if random.randint(1, 6) == 1:
  177.                     aa_hits += 1
  178.             print 'aa gun hits = ', aa_hits
  179.             for i in a_units:
  180.                 while ((i[3] == 'fight') or (i[3] == 'bomb')) and ((i[0] > 0) and (aa_hits > 0)):
  181.                     i[0] = i[0] - 1
  182.                     aa_hits = aa_hits - 1
  183.         return a_units
  184.  
  185.     def fire_battb_and_remove_casualties(self, a_units, d_units):
  186.         bombard_hits = 0
  187.         for i in a_units:
  188.             if (i[3] == 'battb') and (i[0] > 0):
  189.                 for k in range(i[0]):                
  190.                     if random.randint(1, 6) <= 4:
  191.                         bombard_hits += 1
  192.                 for j in d_units:
  193.                     while (bombard_hits > 0) and (j[0] > 0):
  194.                         j[0] = j[0] - 1
  195.                         bombard_hits = bombard_hits - 1
  196.         a_units[8][0] = 0
  197.         return d_units
  198.    
  199.     def remove_sub_insta_kills(self, units, sub_insta_kills): #submarine kills don't allow victim unit to fire back
  200.         passer = 0                                                  #except (undamaged) two hit battleships
  201.         for i in units:
  202.             while (i[0] > 0) and (sub_insta_kills > 0):
  203.                 if (i[3] == 'fight') or (i[3] == 'bomb'):
  204.                     #subs aren't allowed to destroy planes
  205.                     passer += 1
  206.                     if passer == 3:
  207.                         sub_insta_kills = 0 #nothing present that subs can kill
  208.                 else:
  209.                     i[0] = i[0] - 1
  210.                     sub_insta_kills = sub_insta_kills - 1
  211.         return units
  212.  
  213.     def check_if_battle_over(self, a_units, d_units, a_wins, d_wins, draw, iterations):
  214.         restart_round = 1; a_dead = 1; d_dead = 1; a_won = 0; d_won = 0
  215.         for i in a_units:
  216.             if i[0] > 0: #if any units alive
  217.                 a_dead = 0
  218.         if a_dead == 1:
  219.             d_wins += 1
  220.             d_won = 'yes'
  221.         for i in d_units:
  222.             if i[0] > 0:
  223.                 d_dead = 0
  224.         if d_dead == 1:
  225.             a_wins += 1
  226.             a_won = 'yes'
  227.         if (a_dead == 1) and (d_dead == 1):
  228.             draw += 1; a_wins = a_wins - 1; d_wins = d_wins - 1
  229.         if (a_dead == 1) or (d_dead == 1):
  230.             iterations += 1
  231.             restart_round = 0
  232.         return a_wins, d_wins, draw, iterations, restart_round, a_won, d_won
  233.  
  234.     def run_battle(self, a_units, d_units):
  235.         desired_iterations = input('How many times do you want to run the battle?')
  236.         rerun = 1
  237.         while rerun == 1:
  238.             iterations = 0; a_wins = 0; d_wins = 0; draw = 0; average_units_left = [0, 0]
  239.             while iterations < desired_iterations:
  240.                 restart_round = 1
  241.                 print 'processing battle #', iterations + 1
  242.                 dupes = x.duplicate_original_armies(o_a_units, o_d_units)
  243.                 a_units = dupes[0]; d_units = dupes[1]
  244.                 while restart_round == 1:
  245.                     a_units = x.fire_aa_and_remove_aa_casualties(d_units[10][0], a_units)
  246.                     d_units[10][0] = 0
  247.  
  248.                     total_a_hits = x.roll(a_units, 1, 'a', a_units, d_units)
  249.                     a_hits = total_a_hits[0][0]; sub_insta_kills = total_a_hits[1]
  250.                    
  251.                     d_units = x.remove_sub_insta_kills(d_units, sub_insta_kills)
  252.                     d_units = x.fire_battb_and_remove_casualties(a_units, d_units)
  253.  
  254.                     total_d_hits = x.roll(d_units, 2, 'd', a_units, d_units)
  255.                     d_hits = total_d_hits[0][0]
  256.                     d_sub_hits = total_d_hits[2]
  257.                    
  258.                     x.remove_casualties(a_units, d_hits, d_sub_hits)
  259.                     x.remove_casualties(d_units, a_hits, 0)
  260.                    
  261.                     y = x.check_if_battle_over(a_units, d_units, a_wins, d_wins, draw, iterations)
  262.                     a_wins = y[0]; d_wins = y[1]; draw = y[2]; iterations = y[3]; restart_round = y[4]
  263.                     a_units[7][0] = a_units[7][0] / 2; d_units[7][0] = d_units[7][0] / 2
  264.                    
  265.                     if y[5] == 'yes': #if a won
  266.                         for i in a_units:
  267.                                 for j in range(i[0]):
  268.                                     average_units_left[0] += 1
  269.                     elif y[6] == 'yes': #if d won
  270.                         for i in d_units:
  271.                             for j in range(i[0]):
  272.                                 average_units_left[1] += 1
  273.  
  274.                     a_units[7][0] = a_units[7][0] * 2; d_units[7][0] = d_units[7][0] * 2                                            
  275.             rerun = x.statistics(a_wins, d_wins, draw, iterations, average_units_left)
  276.  
  277.     def statistics(self, a_wins, d_wins, draw, iterations, average_units_left):
  278.         print '\nResults for', iterations, 'simulations'
  279.         print '\nAttacker win % =', float(a_wins) / iterations * 100,
  280.         if a_wins > 0:
  281.             print ' Average units left:', float(average_units_left[0]) / a_wins
  282.         print 'Defender win % =', float(d_wins) / iterations * 100,    
  283.         if d_wins > 0:
  284.             print ' Average units left:', float(average_units_left[1]) / d_wins
  285.         print 'Draw % =', float(draw) / iterations * 100
  286.         return input('\nRerun last simulation? 0 for no, 1 for yes')
  287.                
  288.  
  289. program_restart = 1
  290. restart_round = 1
  291.  
  292. while program_restart == 1:
  293.     x = mainClass()
  294.     o_a_units = x.army_chooser('attacking')
  295.     o_d_units = x.army_chooser('defending')
  296.     z = x.run_battle(o_a_units, o_d_units)
  297.     program_restart = input('\nRestart Program? 0 for no, 1 for yes')
  298. raw_input('exit')
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement