-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgame.py
More file actions
346 lines (311 loc) · 14.8 KB
/
Copy pathgame.py
File metadata and controls
346 lines (311 loc) · 14.8 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
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
"""Billy in the Fat Lane - A Lame Life Simulation Game
Copyright (C) 2013 Chris Parlette, Matt Parlette
This file is part of Billy in the Fat Lane.
Billy in the Fat Lane is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Billy in the Fat Lane is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Billy in the Fat Lane. If not, see http://www.gnu.org/licenses/."""
from uuid import uuid4
from menu import NewGameMenu,TurnMenu, MoveMenu, JobMenu, CourseMenu, BuyMenu, ListMenu, QuitMenu
from player import Player, Health, Knowledge, Happiness, Money
from map import Map
import os
class Game:
def __init__(self, map = None, debug = False):
self.id = uuid4()
self.debug = debug
#Valid commands this game class will accept
self.commands = ["move","end","job_apply", "job_work", "course_enroll",
"item_buy","item_use"]
#Has the game been started?
self.started = False
#List of player objects
self.players = list()
#Game Board
self.map = map if map else Map()
#Turn Counter
self.turn = 0
#Endgame conditions
self.endgame_conditions = {"health": Health(10),
"knowledge": Knowledge(5),
"happiness": Happiness(5),
"money": Money(20)}
#Save the start location for easier reference
self.start_location = self.map.get_start_location()
def log_debug(self,message):
if self.debug:
print "Game Class:\tDebug:\t%s" % str(message)
def log_error(self,message):
print "Game Class:\tError:\t%s" % str(message)
def get_location(self,symbol):
if symbol and isinstance(symbol,basestring):
for location in self.map.locations:
if symbol == location.symbol:
return location
return None
def start(self):
menu = NewGameMenu()
#Display the menu until the user quits or starts the game
quit_to_main_menu = False
quit_completely = False
while not quit_to_main_menu:
selection = menu.display().lower()
"""Clear the screen, use cls if Windows or clear if Linux"""
if not self.debug:
os.system('cls' if os.name=='nt' else 'clear')
if selection == 'q':
quit_completely, quit_to_main_menu = QuitMenu(options={'m':'Return to the Main Menu','q':'Quit BITFL completely'}).display()
self.log_debug("Results from QuitMenu was"+str(quit_completely)+str(quit_to_main_menu))
if quit_completely:
return self.started, quit_completely
if quit_to_main_menu:
break
if selection == 's':
if not self.players:
print "No players added, please add a player before starting the game."
else:
self.new_turn()
self.started = True
break
if selection == 'a':
name = raw_input("Name: ")
if name is not "":
player = Player(name)
self.players.append(player)
#Set the player with a location to start
player.move(self.map.locations[0])
if selection == 'l':
print "Player List:"
print "\n".join(str(x) for x in self.players)
return self.started, quit_completely
def run(self):
"""Process user commands until they want to exit."""
#Loop until something breaks it, like a quit event
move_menu = MoveMenu(self.map.locations)
quit_to_main_menu = False
while not quit_to_main_menu:
for player in self.players:
if self._finished_game(player):
print "Congratulations %s, you won the game!" % player
quit_to_main_menu = True
else:
turn_done = False
while not turn_done:
menu = TurnMenu()
if player.location.jobs:
menu.add_option('a','Apply for a job')
if player.job in player.location.jobs:
menu.add_option('w','Work')
if player.location.courses:
menu.add_option('c','Enroll in a course')
if player.location.has_items():
menu.add_option('b','Buy Items')
if len(player.items):
menu.add_option('u','Use Item')
selection = menu.display(self.turn,player,player.attributes['time'].get())
"""Clear the screen, use cls if Windows or clear if Linux"""
if not self.debug:
os.system('cls' if os.name=='nt' else 'clear')
if selection == 'q':
quit_completely, quit_to_main_menu = QuitMenu(options={'m':'Return to the Main Menu','q':'Quit BITFL completely'}).display()
self.log_debug("Results from QuitMenu was"+str(quit_completely)+str(quit_to_main_menu))
if quit_completely:
return True
if quit_to_main_menu:
return False
if selection == 'e':
player.attributes['time'].set(value=10)
turn_done = True
if selection == 'm':
self.command("move",{'player':player,'location_symbol':move_menu.display(self.map)})
if selection == 'a':
self.command('job_apply',{'player':player, 'job_rank':JobMenu().display(job_list=player.location.jobs)})
if selection == 'w':
self.command('job_work',{'player':player})
if selection == 'i':
print player.info_display()
if selection == 'c':
self.command('course_enroll',{'player':player, 'course_choice':CourseMenu().display(course_list=player.location.courses, player=player)})
if selection == 'b':
item = BuyMenu().display(player.location.items)
if item:
self.command('item_buy',{'player':player, 'item':item})
if selection == 'u':
item = ListMenu("Select Item to Use",player.items).display()
self.command('item_use',{'player':player, 'item':item})
self.new_turn()
def new_turn(self):
"""Create a new turn and add it to the end of the turns list."""
#Move all players home
for player in self.players:
player.location = self.start_location
#Advance the turn counter
self.turn += 1
def command(self,command,parameters = None):
"""Process a command for a player.
Return a boolean on if the command completed successfully."""
self.log_debug("command(): command is %s" % str(command))
self.log_debug("command(): parameters: %s" % str(parameters))
# Parameters need to be provided
if command is None:
self.log_debug("command(): command was None")
return False
# Parameters need to be valid
if command not in self.commands:
self.log_debug("command(): command was not in self.commands")
return False
if command is "move":
#Move Player
#We're going to start with each movement costing 1 hour, this will likely change
time_cost = -1
#Verify Parameters
if parameters:
if set(['player','location_symbol']).issubset(parameters):
#Check to see if they have enough time to move
if parameters['player'].attributes['time'].get() >= abs(time_cost):
#User may have cancelled on MoveMenu, so make sure a location was passed
if parameters['location_symbol'] != "":
location = self.get_location(parameters['location_symbol'])
self.log_debug("Moving %s to %s" % (parameters['player'],location.name))
parameters['player'].move(location)
parameters['player'].attributes['time'].set(delta=time_cost)
else:
print "No time is left to move!"
else:
self.log_error("Invalid parameters for move command")
else:
self.log_error("Inavlid parameters for apply command")
return False
if command is "job_apply":
#Apply for a job
#Each job application will cost 1 hour to start
time_cost = -1
#Verify Parameters
if parameters:
if set(['player','job_rank']).issubset(parameters):
player = parameters['player']
#Check to see if they have enough time to apply for this job
if player.attributes['time'].get() >= abs(time_cost):
if parameters['job_rank'] != '':
self.log_debug("Looking up job (rank %s) in %s" % (parameters['job_rank'],player.location.name))
job = player.location.get_job_by_rank(parameters['job_rank'])
if job:
self.log_debug("Player %s applying for %s at %s" % (player,job.name,player.location.name))
player.job = job
player.attributes['time'].set(delta=time_cost)
else:
self.log_error("Job (rank %s) not found in %s" % (parameters['job_rank'],player.location.name))
else:
print "No time is left to apply for this job!"
else:
self.log_error("Inavlid parameters for apply command")
else:
self.log_error("Inavlid parameters for apply command")
if command is "job_work":
#Work at the players job
#Currently working takes 1 hour
time_cost = -1
if parameters:
if set(['player']).issubset(parameters):
player = parameters['player']
if player.attributes['time'].get() >= abs(time_cost):
player.attributes['money'].set(delta=player.job.pay)
print "You've earned $%s" % (player.job.pay)
player.attributes['time'].set(delta=time_cost)
else:
print "No time is left for work!"
else:
self.log_error("Inavlid parameters for work command")
else:
self.log_error("Inavlid parameters for work command")
if command is "end":
#End Turn
return True
if command is "course_enroll":
#Take a class
if parameters:
if set(['player','course_choice']).issubset(parameters):
if parameters['course_choice'] != '' and parameters['course_choice'] != None:
player = parameters['player']
self.log_debug("Looking up course %s in %s" % (parameters['course_choice'],player.location.name))
course = player.location.get_course_by_symbol(parameters['course_choice'])
self.log_debug("Course %s being taken" % (course.name))
if course:
#Each class has a time attribute for how long that class takes
time_cost = course.time
if player.attributes['time'].get() >= abs(time_cost):
#Check if the player has enough money to pay for the course
if player.attributes['money'].get() >= abs(course.cost):
self.log_debug("Player %s taking course %s at %s" % (player,course.name,player.location.name))
player.attributes['knowledge'].set(delta=course.knowledge_value)
player.completed_education.append(course.name)
self.log_debug("Player %s now has knowledge %s" % (player,player.attributes['knowledge'].get()))
player.attributes['money'].set(delta=course.cost)
player.attributes['time'].set(delta=time_cost)
else:
print "You don't have enough money to enroll in this course!"
else:
print "You don't have enough time left to take this course!"
else:
self.log_error("Course %s not found in %s" % (parameters['course_choice'],player.location.name))
else:
self.log_error("Inavlid parameters for course_enroll command")
if command is "item_buy":
if parameters:
if set(['player','item']).issubset(parameters):
item = parameters['item']
player = parameters['player']
if item in player.location.items:
if player.attributes['money'].get() >= abs(item.cost):
player.add_item(player.location.get_item(id=item.id,delete=True))
self.log_debug("Moved item (%s) from location (%s) to player (%s)" % (item,player,player.location))
player.attributes['money'].set(delta=item.cost)
else:
print "You don't have enough money for this item"
else:
self.log_error("Item (%s) not found in location (items: %s)" % (item,str(player.location.items)))
else:
self.log_error("Invalid parameters for %s. Parameters received as %s" % (command,str(parameters)))
else:
self.log_error("No parameters received for %s, but they were expected" % command)
if command is "item_use":
if parameters and set(['player','item']).issubset(parameters):
item = parameters['item']
player = parameters['player']
self.log_debug("Player item list: %s" % (str(player.items)))
self.log_debug("Player item list (id): %s" % ([x.id for x in player.items]))
self.log_debug("ID of item: %s" % item.id)
if item in player.items:
if "time" in item.effects and player.attributes['time'].get() >= abs(item.effects['time']):
#use the item
self.log_debug("Consuming item (%s) with effects %s" % (str(item),str(item.effects)))
player.use_item(item)
self.log_debug("Player attributes are now {%s}" % (", ".join(["%s: %s" % (key,player.attributes[key].get()) for (key,value) in player.attributes.items()])))
else:
print "Not enough time left to use this item!"
else:
self.log_error("This item (%s) does not belong to this player (%s)" % (str(item),str(player)))
#If we got here, then something didn't execute correctly
return False
def _finished_game(self,player):
"""Return true if this player has satisfied the endgame conditions."""
if self.endgame_conditions:
for attribute in self.endgame_conditions:
if attribute in player.attributes:
if player.attributes[attribute].get() < self.endgame_conditions[attribute].get():
self.log_debug("%s failed endgame attribute %s (%s is less than goal of %s), returning False" % (player,attribute,player.attributes[attribute].get(),self.endgame_conditions[attribute].get()))
return False
else:
self.log_debug("%s attribute does not exist in Player object %s, returning False" % (attribute,player))
return False
else:
self.log_debug("There are no endgame conditions, _finished_game() is returning False")
return False
#If we got here, then everything is satisfied for the end game
return True