Trivial changes.
[realism.git] / ui / zork_ui.py
blob6e743cbf3664f412e51f624607fb9cf9e7238221
1 # This file is part of Realism, which is Copyright FunnyMan3595 (Charlie Nolan)
2 # and licensed under the GNU GPL v3. For more details, see LICENSE in the main
3 # Realism directory.
5 from sys import stdin, stdout, exit
6 from ui import UI
7 from os import name as os_name
8 from engine.being import abilities
9 from engine.spells import *
10 from engine.game_map import north, south, east, west, directions
11 from game import game
12 party = game.party
14 # If it's available, use the readline-enhanced version of raw_input.
15 try:
16 import readline
17 except ImportError:
18 # Eventually, there should be a minimal wx GUI here that basically implements
19 # history and navigation a la readline. For now, we just fall back to the
20 # basic raw_input.
21 pass
23 class ZorkUI(UI):
24 class_name = "Zork UI"
26 def __init__(self):
27 pass
29 def main_loop(self):
30 input = 'look'
31 while True:
32 self.process_input(input)
33 input = self.get_input()
35 def get_input(self):
36 return raw_input("> ").lower()
38 def process_input(self, input):
39 if not input:
40 return
41 if self.mode == 'map':
42 game_map = self.game_map
43 if input in ('l', 'look'):
44 stdout.write("You are in a stony field. ")
45 open = []
46 blocked = []
47 window = self.game_map.get_window()
48 my_col = my_row = len(window)/2
49 if window[my_row - 1][my_col].type == "empty":
50 open.append("north")
51 else:
52 blocked.append("north")
53 if window[my_row + 1][my_col].type == "empty":
54 open.append("south")
55 else:
56 blocked.append("south")
57 if window[my_row][my_col + 1].type == "empty":
58 open.append("east")
59 else:
60 blocked.append("east")
61 if window[my_row][my_col - 1].type == "empty":
62 open.append("west")
63 else:
64 blocked.append("west")
65 if len(open) == 4:
66 stdout.write("\n")
67 elif len(open) == 3:
68 stdout.write("A large rock blocks your path " + blocked[0] + ".\n")
69 elif len(open) == 2:
70 stdout.write("Large rocks block your path " + blocked[0] + " and " + blocked[1] + ".\n")
71 elif len(open) == 1:
72 stdout.write("Large rocks surround you. There is a clear path " + open[0] + ".\n")
73 else:
74 stdout.write("Large rocks surround you, blocking all movement.\n")
75 if game_map.is_shop():
76 stdout.write("There is a shop here.\n")
77 print game_map.name, game_map.pos
78 elif input in ('n', 'north'):
79 if game_map.go(north) != False:
80 self.process_input('look')
81 else:
82 stdout.write("A large rock blocks your path.\n")
83 elif input in ('s', 'south'):
84 if game_map.go(south) != False:
85 self.process_input('look')
86 else:
87 stdout.write("A large rock blocks your path.\n")
88 elif input in ('e', 'east'):
89 if game_map.go(east) != False:
90 self.process_input('look')
91 else:
92 stdout.write("A large rock blocks your path.\n")
93 elif input in ('w', 'west'):
94 if game_map.go(west) != False:
95 self.process_input('look')
96 else:
97 stdout.write("A large rock blocks your path.\n")
98 elif input in ('enter', 'in', 'shop') or (input == 'i' and game_map.isShop()):
99 if game_map.isShop():
100 game_map.enterShop()
101 self.process_input('look')
102 else:
103 stdout.write("There's no shop here!\n")
104 elif input in ('i', 'inv', 'inventory'):
105 i = 0
106 for item in party.get_items():
107 print "%2d) %-15s %5s Gold (%s)" % (i, item.name, item.value, item.count)
108 i += 1
109 if i == 0:
110 print "You are empty-handed."
111 print "You have %d gold." % party.gold
112 elif input in ('c', 'char', 'character'):
113 for player in party.chars:
114 print "Stats for %s:" % (player.name,)
115 print " Level:", player.level()
116 print " HP: %d/%d" % (player.hp, player.max_hp)
117 print " MP: %d/%d" % (player.mp, player.max_mp)
118 for ability in range(len(player.stats)):
119 print " %-10s %d (%2d%%)" % \
120 (abilities[ability].capitalize() + ":",
121 player.stats[ability],
122 player.stats_xp[ability] * 100)
123 print
124 elif input in ('q', 'quit', 'exit'):
125 exit()
126 else:
127 stdout.write("I don't understand that.\n")
128 elif self.mode == 'shop':
129 split = input.split()
130 if input in ('l', 'look'):
131 i = 0
132 print "Shop contents:"
133 for item in self.shop.getContents():
134 print "%2d) %-15s %5s Gold (%s)" % (i, item.name, item.value, item.count)
135 i += 1
136 if i == 0:
137 print "The shop is empty."
138 print "You have %d gold." % party.gold
139 elif input in ('o', 'out', 'e', 'exit'):
140 self.mode = 'map'
141 self.process_input('look')
142 elif split[0] in ('b', 'buy'):
143 if len(split) == 1:
144 stdout.write("Buy what?\n")
145 elif len(split) > 3:
146 stdout.write("I don't understand that.\n")
147 else:
148 try:
149 item = int(split[1])
150 if len(split) == 3:
151 num = int(split[2])
152 else:
153 num = 1
154 if item >= 0 and item < len(self.shop.getContents()):
155 msg = self.shop.buy(item, num)
156 if msg:
157 stdout.write(msg)
158 else:
159 self.process_input('look')
160 else:
161 stdout.write("I don't see that item.\n")
162 except ValueError:
163 stdout.write("I don't understand that.\n")
164 elif split[0] in ('s', 'sell'):
165 if len(split) == 1:
166 stdout.write("Sell what?\n")
167 elif len(split) > 3:
168 stdout.write("I don't understand that.\n")
169 else:
170 try:
171 item = int(split[1])
172 if len(split) == 3:
173 num = int(split[2])
174 else:
175 num = 1
176 if item >= 0 and item < len(party.get_items()):
177 msg = self.shop.sell(item, num)
178 if msg:
179 stdout.write(msg)
180 else:
181 self.process_input('look')
182 else:
183 stdout.write("I don't see that item.\n")
184 except ValueError:
185 stdout.write("I don't understand that.\n")
186 elif input in ('i', 'inv', 'inventory'):
187 i = 0
188 for item in party.get_items():
189 print "%2d) %-15s %5s Gold (%s)" % (i, item.name, item.value, item.count)
190 i += 1
191 if i == 0:
192 print "You are empty-handed."
193 print "You have %d gold." % party.gold
194 elif input in ('q', 'Q', 'quit', 'Quit'):
195 exit()
196 else:
197 stdout.write("I don't understand that.\n")
198 elif self.mode == "battle":
199 if input in ('l', 'look'):
200 for critter in self.battle.party.chars:
201 print "%s looks %s." \
202 % (critter.name.capitalize(), critter.health())
203 elif input in ('r', 'run', 'flee'):
204 event = self.battle.run(0)
205 critters = event.getTargets()
206 results = event.getResults()
207 for (critter, escaped) in map(None, critters, results):
208 if escaped:
209 print "You escape from %s!" % critter.name
210 else:
211 print "%s follows you." % critter.name.capitalize()
212 if not self.battle.over():
213 self.was_attacked(self.battle.group_defend())
214 elif input in ('a', 'attack'):
215 if not self.i_attacked(0, self.battle.attack(0, 0)):
216 self.was_attacked(self.battle.group_defend())
217 elif input in ('h', 'heal'):
218 if heal in party.get_spells():
219 me = party.chars[0]
220 mana = me.mp
221 event = self.battle.cast(me, me, heal)
222 mana -= me.mp
223 if event.target == []:
224 print "You don't have enough mana!"
225 else:
226 healing = -event.result
227 print "You spend %d mana to heal yourself for %d health." % (mana, healing)
228 print "You now have %d/%d health and %d/%d mana." % \
229 (me.hp, me.max_hp, me.mp, me.max_mp)
230 self.was_attacked(self.battle.group_defend())
231 else:
232 print "You need a healing stone to cast Heal."
233 elif input in ('f', 'fire', 'fireball'):
234 me = party.chars[0]
235 target = self.battle.party.chars[0]
236 mana = me.mp
237 event = self.battle.cast(me, target, fireball)
238 mana -= me.mp
239 target = event.target
240 damage = event.result
242 if target == []:
243 print "You don't have enough mana!"
244 elif damage == "miss":
245 print "You spend %d mana to cast a fireball at %s, but it is resisted." % (mana, target.name)
246 elif target.hp > 0 and damage > 0:
247 print "You spend %d mana to cast a fireball at %s, dealing %d damage." % (mana, target.name, damage)
248 elif target.hp <= 0 and damage > 0:
249 print "You spend %d mana to cast a fireball at %s, killing %s." % (mana, target.name, target.pronoun_object)
250 elif damage == 0:
251 print "You spend %d mana to cast a fireball at %s, with no effect." % (mana, target.name)
252 else:
253 print "You spend %d mana to cast a fireball at %s, healing %s." % (mana, target.name, target.pronoun_object)
254 if target != [] and not self.battle.over():
255 self.was_attacked(self.battle.group_defend())
256 elif input in ('q', 'quit'):
257 exit()
258 else:
259 stdout.write("I don't understand that.\n")
260 else:
261 stdout.write("Unsupported UI mode.\n")
262 exit()
264 def i_attacked(self, character, event):
265 if event.target.hp <= 0:
266 print "You killed %s!" % event.target.name
267 if self.battle.over():
268 return True
269 elif event.result == "miss":
270 print "You missed."
271 else:
272 print "You hit %s for %d damage." % (event.target.name, event.result)
274 def was_attacked(self, events):
275 for event in events:
276 print event.source.name.capitalize(),
277 if event.result == "miss":
278 print "missed."
279 else:
280 print "hit %s for %d damage. %s has %d health left." % \
281 (event.target.name, event.result, event.target.pronoun.capitalize(), event.target.hp)
282 if party.is_dead():
283 print "You have been slain!"
284 exit()
286 def hp_tick(self, character, amount):
287 if amount > 0:
288 print "Your health increases by %d, to a total of %d." % (amount, party.chars[character].hp)
290 def mp_tick(self, character, amount):
291 if amount > 0:
292 print "You gain %d mana. You have %d mana." % (amount, party.chars[character].mp)
294 def gained_ability_level(self, character, ability):
295 print "Your %s improves!" % abilities[ability]
297 def gained_level(self, character):
298 print "You gain a level!"
300 def won_battle(self):
301 self.map_mode()
302 self.process_input("look")
304 def map_mode(self, game_map = None):
305 self.mode = 'map'
306 if game_map:
307 self.game_map = game_map
309 def shop_mode(self, shop = None):
310 self.mode = 'shop'
311 if shop:
312 self.shop = shop
314 def battle_mode(self, battle = None):
315 self.mode = 'battle'
316 if battle:
317 self.battle = battle
318 print "You are attacked by %d critters!" % len(battle.party.chars)
320 def conversation_mode(self, conversation = ""):
321 print conversation