-
Notifications
You must be signed in to change notification settings - Fork 2
/
world.py
177 lines (158 loc) · 6.3 KB
/
world.py
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
#!/usr/bin/python3
#
# Coat of arms is an email-based, CLI strategy game of conquest.
# This module holds the representations of all in-game entities.
#
# Copyright (c) 2015 Daniel Vedder, Christopher Borchert
# Licensed under the terms of the MIT license.
#
import xml.etree.ElementTree as xmlET
global unit_cost
unit_cost = 2000
class Territory:
def __init__(self, name, tax, neighbours=[], owner="", units=[]):
self.name = name
self.tax = tax
self.neighbours = neighbours
self.owner = owner
self.units = units
def add_neighbour(self, neighbour):
"Add a neighbour to this territory (by name)"
if neighbour not in self.neighbours:
self.neighbours.append(neighbour)
print(self.name+" now has the neighbours "+str(self.neighbours))
def add_unit(self, unit):
"Add a unit to this territory (by UID)"
if unit not in self.units:
self.units.append(unit)
class Occupations:
"A list of possible activities for army units"
# Better done with enums, but they aren't introduced until Python 3.4
RESTING = 0
MARCHING = 1
TRAINING = 2
FIGHTING = 3
class Unit:
def __init__(self, uid, location, max_size=100, strength=5, name=""):
self.uid = uid #A unique id consisting of player name + id number
self.max_size = self.size = max_size
self.strength = strength
self.name = name
self.location = location
self.current_occupation = Occupations.RESTING
self.training_units = 0
def change_size(self, amount):
''' Change the size of this unit by amount. Method returns -1 if the
unit dies, otherwise returns 0.
'''
self.size = self.size + amount
if self.size > self.max_size:
self.size = self.max_size
elif self.size <= 0:
return -1 #replace this with a custom error?
else: return 0
def train(self):
''' Tell a unit to train. For every three turns spent training, the unit
gains one strength point.
'''
self.current_occupation = Occupation.TRAINING
self.training_units = self.training_units + 1
if self.training_units % 3 == 0:
self.strength = self.strength + 1
class Player:
def __init__(self, name, gold=0, territories=[], units={}):
#TODO replace args with kwargs
self.name = name
self.units = units
self.territories = territories
self.gold = gold
self.uid_counter = 1
def new_unit(self, location):
''' The player buys a new unit that is set down at the specified
location. If the player has insufficient funds, nothing happens and
the method returns -1.
'''
global unit_cost
if self.gold >= unit_cost:
self.gold = self.gold - unit_cost
uid = self.name+str(self.uid_counter)
self.uid_counter = self.uid_counter + 1
self.units[uid] = Unit(uid, location)
return 0
else: return -1
def upgrade_unit(self, uid):
''' The player upgrades a unit (i.e. increases it's max size by one).
Requires unit_cost / 50 gold. If the player has insufficient funds, the
method does nothing and returns -1, otherwise it returns 0.
'''
global unit_cost
if self.gold >= unit_cost / 50:
self.gold = self.gold - unit_cost / 50
self.units[uid].max_size = self.units[uid].max_size + 1
return 0
else: return -1
class World:
def __init__(self, world_file=None):
self.players = {}
self.territories = {}
self.random_seed = None
if world_file:
self.load_world(world_file)
def load_world(self, file_name):
"Parse the given world file"
world_tree = xmlET.parse(file_name)
tree_root = world_tree.getroot()
self.random_seed = int(tree_root.find('seed').text)
# Load all territories
for t in tree_root.findall('territory'):
name = t.attrib.get('name')
tax = int(t.find('tax').text)
owner = t.find('owner').text
neighbours = []
for n in t.findall('neighbour'): neighbours.append(n.text)
units = []
for u in t.findall('unit'): units.append(u.text)
self.territories[name] = Territory(name, tax, neighbours,
owner, units)
# Load the players
for p in tree_root.findall('player'):
name = p.attrib.get('name')
gold = int(p.find('gold').text)
territories = []
for t in p.findall('territory'): territories.append(t.text)
units = {}
for u in p.findall('unit'):
uid = u.attrib.get('uid')
u_name = u.attrib.get('name', "")
max_size = u.attrib.get('max_size')
size = u.attrib.get('size')
strength = u.attrib.get('strength')
location = u.attrib.get('location')
units[uid] = Unit(uid, max_size, strength, location, u_name)
self.players[name] = Player(name, gold, territories, units)
def pretty_print(self):
"This is primarily a debugging function"
print("World:\n======")
print("Random seed: "+str(self.random_seed)+"\n")
for t in self.territories.items():
print("Territory "+t[0]+":")
print("> Owner is "+str(t[1].owner))
print("> "+str(t[1].tax)+" gold taxes")
neighbours = ""
for n in t[1].neighbours: neighbours = n+" "+neighbours
print("> Neighbours: "+neighbours)
t_units = ""
for tu in t[1].units: t_units = tu+" "+t_units
print("> Units: "+t_units)
for p in self.players.items():
print("Player "+p[0]+":")
print("> "+str(p[1].gold)+" gold")
territories = ""
for t in p[1].territories: territories = t+" "+territories
print("> Territories: "+territories)
p_units = ""
for pu in p[1].units.items(): p_units = pu[1].uid+" "+p_units
print("> Units: "+p_units)
if __name__ == '__main__': #debugging
w = World('example_world.xml')
w.pretty_print()