OpenCores
URL https://opencores.org/ocsvn/c0or1k/c0or1k/trunk

Subversion Repositories c0or1k

[/] [c0or1k/] [trunk/] [tools/] [cml2-tools/] [cmladvent.py] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 drasko
#!/usr/bin/env python
2
#
3
# cmladvent.py -- CML2 configurator adventure-game front end
4
# by Eric S. Raymond, <esr@thyrsus.com>
5
#
6
# This illustrates how easy it is to wrap a front end around cmlsystem.
7
# Purely in the interests of science, of course...
8
#
9
import sys
10
 
11
if sys.version[0] < '2':
12
    print "Python 2.0 or later is required for this program."
13
    sys.exit(0)
14
 
15
import os, string, getopt, cmd, time, whrandom, random
16
import cml, cmlsystem
17
 
18
# Globals
19
debug = 0
20
proflog = partialsave = None
21
banner = ""
22
gruestate = darkturns = 0
23
lanternloc = None
24
configfile = None
25
configuration = None
26
 
27
directions = ('n','e','s','w','ne','sw','se','nw','dn','up')
28
 
29
# User-visible strings in the configurator.  Separated out in order to
30
# support internationalization.
31
_eng = {
32
    # Strings used in the command help -- these should align
33
    "LHELP":"look [target] -- look here or at target (direction or option).",
34
    "NHELP":"nearby        -- list nearby rooms (useful with go)",
35
    "GHELP":"go            -- go to a named menu (follow with the label).",
36
    "IHELP":"inventory     -- show which options you have picked up.",
37
    "THELP":"take [module] -- set options, follow with option names.",
38
    "SETHELP":"set           -- set numeric or string; follow with symbol and value.",
39
    "DHELP":"drop          -- unset options, follow with option names or `all'.",
40
    "LDHELP":"load          -- read in a configuration (follow with the filename).",
41
    "SHELP":"save          -- save the configuration (follow with a filename).",
42
    "XYZZY":"xyzzy         -- toggle suppression flag.",
43
    "QHELP":"quit          -- quit, discarding changes.",
44
    "XHELP":"exit          -- exit, saving the configuration.",
45
    # Grue/lantern messages
46
    "BRASSOFF":"A brass lantern (unlit).",
47
    "BRASSON":"A brass lantern (lit).",
48
    "DARK":"It is very dark.  If you continue, you are likely to be eaten by a grue.",
49
    "EATEN":"*CHOMP*!  You have been eaten by a slavering grue.  Game over.",
50
    "GLOW":"The lantern radiates a mellow golden light.",
51
    "LANTERN":"lantern",
52
    "LANTERNDROP":"Lantern: dropped.",
53
    "LANTERNTAKE":"Lantern: taken.",
54
    "LONGLANTERN":"A brass lantern is here.",
55
    "LANTERNHELP":"""
56
You see a brass lantern with a ring-shaped handle, hooded and paned with
57
clear glass.  A toggle on the lamp connects to a firestriker inside it.
58
On the bottom is stamped a maker's mark that reads:
59
 
60
       Another fine product of FrobozzCo.
61
     Made in Plumbat, Great Underground Empire
62
""",
63
    # Other strings
64
    "ABORTED":"Configurator aborted.",
65
    "BADOPTION":"cmladvent: unknown option on command line.\n",
66
    "BOOLEAN":"`y' and `n' can only be applied to booleans or tristates",
67
    "CANNOTSET":"    Can't assign this value for bool or trit symbol.",
68
    "CONSTRAINTS":"Constraints:",
69
    "DEFAULT":"Default: ",
70
    "DERIVED":"Symbol %s is derived and cannot be set.",
71
    "DIRHELP":"You can move in compass directions n,e,w,s,ne,nw,se,sw, up, or dn for down.",
72
    "DONE":"Done",
73
    "DROPPED":"%s: dropped.",
74
    "EFFECTS":"Side effects:",
75
    "EH?":"Eh?",
76
    "EXIT":"Exit",
77
    "EXITS":"Passages exit up, %s.",
78
    "EXTRAROOMS":"Other nearby rooms are: %s.",
79
    "GOODBYE":"You emerge, blinking, into the daylight.",
80
    "INROOM":"In %s room.",
81
    "INVISIBLE":"Symbol is invisible",
82
    "ISHERE":"There is an option named %s here.",
83
    "LOADFAIL":"Loading '%s' failed, continuing...",
84
    "MDISABLED":"Module-valued symbols are not enabled",
85
    "MNOTVALID":"   m is not a valid value for %s",
86
    "NEW":"(NEW)",
87
    "NNOTVALID":"   n is not a valid value for %s",
88
    "NOANCEST":"No ancestors.",
89
    "NOBUTTON":"I don't see button %s here.",
90
    "NOCMDLINE":"%s is the wrong type to be set from the command line",
91
    "NODEPS":"No dependents.",
92
    "NODIR":"You see nothing special in that direction.",
93
    "NOFILE":"cmlconfigure: '%s' does not exist or is unreadable.",
94
    "NOHAVE":"You don't have %s.",
95
    "NOHELP":"No help available for %s",
96
    "NOHERE":"I see no `%s' here.",
97
    "NOMATCHES":"No matches.",
98
    "NONEXIST":"No such location.",
99
    "NOSUCHAS":"No such thing as",
100
    "NOTSAVED":"Configuration not saved",
101
    "NOWAY":"You can't go in that direction from here.",
102
    "OUTOFBOUNDS":"Legal values are in %s",
103
    "PARAMS":"    Config = %s, prefix = %s",
104
    "PASSAGEALL":"Passages lead off in all directions.",
105
    "PASSAGEUP":"A passage leads upwards.",
106
    "PHELP":"press         -- press a button (follow with the button name).",
107
    "POSTMORTEM":"The ruleset was inconsistent.  A state dump is in the file `post.mortem'.",
108
    "REALLY":"Really exit without saving?",
109
    "ROLLBACK":"%s=%s would have violated these requirements:",
110
    "ROOMBANNER":"The %s room.  A sign reads `%s'.",
111
    "SAVEAS":"Save As...",
112
    "SAVEEND":"Done",
113
    "SAVESTART":"Saving %s",
114
    "SAVING":"Saving...",
115
    "SHOW_ANC":"Show ancestors of symbol: ",
116
    "SHOW_DEP":"Show dependents of symbol: ",
117
    "SIDEEFFECTS":"Side Effects",
118
    "SIDEFROM":"Side effects from %s:",
119
    "SUPPRESSOFF":"Suppression turned off.",
120
    "SUPPRESSON":"Suppression turned on.",
121
    "SYMUNKNOWN":"cmlconfigure: unknown symbol %s\n",
122
    "TAKEN":"%s: taken.",
123
    "TRIT":"`m' can only be applied to tristates",
124
    "TRYPRESS":"That doesn't work.  You might try pressing another button.",
125
    "TWISTY":"You are in a maze of twisty little %s menus, all different.",
126
    "USESET":"What?  Configure %s with your bare hands?",
127
    "VALUE":"Value of %s is %s.",
128
    "VISIBLE":"Symbol is visible.",
129
    "VISIBILITY":"Visibility: ",
130
    "WALLCHOICE":"There is a row of buttons on the wall of this room. They read:",
131
    "WALLDEFAULT":"The button marked %s is pressed.",
132
    "WELCOME":"Welcome to CML2 Adventure, version %s.",
133
    # General help
134
    "GENHELP":"""Welcome to the adventure configurator.  For a command summary, type `commands'.
135
In general, a three-letter abbreviation of any command word is sufficient
136
to identify it to the parser.
137
 
138
This interface emulates the style of classic text adventure games such as
139
Colossal Cave Adventure and Zork.  Configuration menus are rooms, and
140
configuration options are objects that can be taken and dropped (except
141
for choice/radiobutton symbols, which become buttons on various room walls).
142
Objects and rooms may silently appear and disappear as visibilities
143
change.
144
 
145
Have fun, and beware of the lurking grue!
146
"""
147
}
148
 
149
grafitti = (
150
    'N tensvggb ernqf: "Gur Jhzchf jnf urer.  Nera\'g lbh tynq ur\'f abg urer abj?"',
151
    'N tensvggb ernqf: "Uryyb, fnvybe!"',
152
    'N tensvggb ernqf: "Sebqb yvirf!"',
153
    'N tensvggb ernqf: "Guvf fcnpr sbe erag."',
154
    'N tensvggb ernqf: "Guvf Jnl gb gur Rterff..."',
155
    # Bofpher Pbybffny Pnir Nqiragher ersreraprf ortva urer.
156
    'Ba bar jnyy vf n tynff-sebagrq obk ubyqvat na nkr.\aBa gur tynff vf jevggra: "OERNX TYNFF VA PNFR BS QJNEIRF"',
157
    'N tensvggb ernqf: "Srr svr sbr sbb!',
158
    # Bofpher Mbex ersreraprf ortva urer.
159
    'N tensvggb ernqf: "Ragunevba gur Jvfr fyrcg urer."',
160
    'N tensvggb ernqf: "N mbexzvq fnirq vf n mbexzvq rnearq."',
161
    'Bar jnyy qvfcynlf n sbezny cbegenvg bs W. Cvrecbag Syngurnq.',
162
    'Bar jnyy qvfcynlf n qhfgl cbegenvg bs gur Rzcrebe Zhzob VV.',
163
    'Bar jnyy qvfcynlf n cvpgher bs gur terng tenabyn fzrygref bs Cyhzong.',
164
    'Bar jnyy qvfcynlf n gnpxl oynpx-iryirg cnvagvat bs n tbyqra-sheerq zvak jvgu uhtr rlrf.',
165
    # Bofpher Q&Q ersreraprf ortva urer
166
    'N tensvggb ernqf: "Vg pbhyq bayl or orggre ng Pnfgyr Terlunjx"',
167
    'N tensvggb ernqf: "Cnenylfvf vf va gur rlr bs gur orubyqre"',
168
    # Bofpher wbxr sbe QrPnzc/Cengg snaf
169
    'N tensvggb ernqf: "Lativ vf n ybhfr!"',
170
    # Abg-fb-bofpher Yvahk ersreraprf ortva urer.
171
    'Ba bar jnyy vf n cubgbtencu bs Yvahf Gbeinyqf, qevaxvat Thvaarff.',
172
    'N jnyy oenpxrg ubyqf n qvfpneqrq cnve bs Nyna Pbk\'f fhatynffrf.  Oebamrq.',
173
    'Ba bar jnyy vf n cbegenvg bs EZF va shyy Fg. Vtahpvhf qent.',
174
    'Ba bar jnyy vf n cvpgher bs Yneel Jnyy ubyqvat n ynetr chzcxva.',
175
    'Ba bar jnyy vf jung nccrnef gb or n cubgbtencu bs Thvqb\'f gvzr znpuvar.',
176
    'Gur sybbe vf yvggrerq jvgu fcrag .45 furyyf. Revp Enlzbaq zhfg unir orra urer.',
177
    )
178
grafittishuffle = []
179
grafitticount = 0
180
 
181
# Eventually, do more intelligent selection using LOCALE
182
lang = _eng
183
 
184
def roll(n):
185
    "Return a random number in the range 0..n-1."
186
    return random.randrange(n)
187
 
188
def shuffle(size):
189
    "Generate a random permutation of 0...(size - 1)."
190
    shuffle = range(size)
191
    for i in range(1, size+1):
192
        j = random.randrange(i)
193
        holder = shuffle[i - 1]
194
        shuffle[i - 1] = shuffle[j]
195
        shuffle[j] = holder
196
    return shuffle
197
 
198
def rot13(str):
199
    res = ""
200
    for c in str:
201
        if c in string.uppercase:
202
            res += chr(ord('A') + ((ord(c)-ord('A')) + 13) % 26)
203
        elif c in string.lowercase:
204
            res += chr(ord('a') + ((ord(c)-ord('a')) + 13) % 26)
205
        else:
206
            res += c
207
    return res
208
 
209
def newroom(room):
210
    # There is a chance of grafitti
211
    global grafitticount, grafittishuffle
212
    if grafitticount < len(grafitti):
213
        if not hasattr(room, "visits") and roll(3) == 0:
214
            room.grafitti = grafitti[grafittishuffle[grafitticount]]
215
            grafitticount += 1
216
    # State machine for lantern and grue
217
    global lanternloc, gruestate, darkturns
218
    if gruestate == 0:           # Initial state
219
        if not hasattr(room, "visits") and roll(4) == 0:
220
            gruestate += 1
221
            lanternloc = room
222
    elif gruestate == 1:        # Lantern has been placed
223
        if roll(4) == 0:
224
            gruestate += 1
225
    elif gruestate == 2:        # It's dark now
226
        darkturns += 1
227
        if darkturns > 2 and roll(4) == 0:
228
            print lang["EATEN"]
229
            raise SystemExit
230
 
231
def visit(room, level=0):
232
    "Visit a room, and describe at any of four verbosity levels."
233
    # 0 = quiet, 1 = name only, 2 = name + help,
234
    # 3 = name + help + exits, 4 = name + help + exits + contents
235
    configuration.visit(room)
236
    # Compute visible exits
237
    room.exits = filter(lambda x: x.type in ("menu", "choices"), room.items)
238
    room.exits = filter(configuration.is_visible, room.exits)
239
    # This way of assigning directions has the defect that they may
240
    # change as submenus become visible/invisible.  Unfortunately,
241
    # the alternative is not being able to assign directions at all
242
    # for long menus.
243
    room.directions = {}
244
    for (dir,other) in zip(directions[:-1], room.exits):
245
        room.directions[dir] = other
246
    if level == 0:
247
        return
248
    elif level == 1:
249
        print lang["INROOM"] % room.name
250
    else:
251
        print lang["ROOMBANNER"] % (room.name, room.prompt)
252
        # Only display room exits at level 3 or up
253
        if level >= 3:
254
            if len(room.exits) > 9:
255
                print lang["PASSAGEALL"]
256
            elif room.exits:
257
                print lang["EXITS"] % ", ".join(room.directions.keys())
258
            elif room != configuration.start:
259
                print lang["PASSAGEUP"]
260
            print
261
        # Display help at level 2 or up
262
        help = room.help()
263
        if help:
264
            sys.stdout.write(help)
265
        # Display grafitti at level 2 or up.
266
        if hasattr(room, "grafitti"):
267
            print rot13(room.grafitti) + "\n"
268
    # Only display other contents of room at level 4 or up
269
    if level >= 4:
270
        if room.type == "choices":
271
            print lang["WALLCHOICE"]
272
            print ", ".join(map(lambda x:x.name, room.items))
273
            print lang["WALLDEFAULT"] % room.menuvalue.name
274
        else:
275
            for symbol in room.items:
276
                if symbol.is_symbol() and configuration.is_visible(symbol) and not symbol.eval():
277
                    print lang["ISHERE"] % symbol.name
278
    # Some things are always shown
279
    if lanternloc == room:
280
        print lang["LONGLANTERN"]
281
    if gruestate == 2:
282
        print lang["DARK"]
283
 
284
def inventory():
285
    # Write mutable symbols, including defaulted modular symbols.
286
    configuration.module_suppress = 0
287
    if lanternloc == 'user':
288
        if gruestate == 3:
289
            print lang["BRASSON"]
290
        else:
291
            print lang["BRASSOFF"]
292
    __inventory_recurse(configuration.start)
293
    if configuration.trit_tie:
294
        configuration.module_suppress = (configuration.trit_tie.eval() == cml.m)
295
    # Write all derived symbols
296
    #config_sh.write(configuration.lang["SHDERIVED"])
297
    #for entry in configuration.dictionary.values():
298
    #    if entry.is_derived():
299
    #        __inventory_recurse(entry, config_sh)
300
 
301
def __inventory_recurse(node):
302
    if not configuration.saveable(node):
303
        return
304
    elif node.items:
305
        for child in node.items:
306
            __inventory_recurse(child)
307
    elif node.type != 'message':
308
        symname = configuration.prefix + node.name
309
        value = node.eval(configuration.debug)
310
        if not value or not node.setcount:
311
            return
312
        try:
313
            if node.type == "decimal":
314
                sys.stdout.write("%s=%d\n" % (symname, value))
315
            elif node.type == "hexadecimal":
316
                sys.stdout.write("%s=0x%x\n" % (symname, value))
317
            elif node.type == "string":
318
                sys.stdout.write("%s=\"%s\"\n" % (symname, value))
319
            elif node.type in ("bool", "trit"):
320
                sys.stdout.write("%s=%s\n" % (symname, `value`))
321
        except:
322
            (errtype, errval, errtrace) = sys.exc_info()
323
            print "Internal error %s while writing %s." % (errtype, node)
324
            raise SystemExit, 1
325
 
326
class advent_menu(cmd.Cmd):
327
    "Adventure-game interface class."
328
 
329
    def set_symbol(self, symbol, value, freeze=0):
330
        "Set the value of a symbol -- line-oriented error messages."
331
        if symbol.is_numeric() and symbol.range:
332
            if not configuration.range_check(symbol, value):
333
                print lang["OUTOFBOUNDS"] % (symbol.range,)
334
                return 0
335
        (ok, effects, violations) = configuration.set_symbol(symbol, value, freeze)
336
        if effects:
337
            print lang["EFFECTS"]
338
            sys.stdout.write(string.join(effects, "\n") + "\n\n")
339
        if not ok:
340
            print lang["ROLLBACK"] % (symbol.name, value)
341
            sys.stdout.write(string.join(violations, "\n") + "\n")
342
        return ok
343
 
344
    def __init__(self, myconfigfile=None, mybanner=""):
345
        cmd.Cmd.__init__(self)
346
        self.configfile = myconfigfile
347
        if mybanner and configuration.banner.find("%s") > -1:
348
            self.banner = configuration.banner % mybanner
349
        elif banner:
350
            self.banner = mybanner
351
        else:
352
            self.banner = configuration.banner
353
        self.current = configuration.start;
354
        self.prompt = "> "
355
        print lang["TWISTY"]%(configuration.banner,)
356
        self.last = None
357
        visit(configuration.start, 4)
358
 
359
    def do_look(self, line):
360
        if not line:                    # Look at where we are
361
            visit(self.current, 4)
362
        elif line == "up":              # Look up
363
            if self.current == configuration.start:
364
                print lang["NODIR"]
365
            else:
366
                visit(self.current.menu, 2)
367
        elif line in directions:        # Look in a direction
368
            if line in self.current.directions.keys():
369
                visit(self.current.directions[line], 2)
370
            else:
371
                print lang["NODIR"]
372
        # Look at an option
373
        elif line in map(lambda x: x.name, filter(lambda x: x.is_logical(), self.current.items)):
374
            symbol = configuration.dictionary[line]
375
            print lang["VALUE"] % (line, symbol.eval())
376
            help = symbol.help()
377
            if help:
378
                sys.stdout.write(help)
379
        else:
380
            print lang["NOHERE"] % line
381
    do_loo = do_look
382
 
383
    def do_nearby(self, dummy):
384
        if self.current != configuration.start:
385
            print lang["ROOMBANNER"] % (self.current.menu.name, self.current.menu.prompt)
386
        for (dir, symbol) in self.current.directions.items():
387
            if symbol.type in ("menu", "choices") and configuration.is_visible(symbol):
388
                print ("%-2s: " % dir) + lang["ROOMBANNER"] % (symbol.name, symbol.prompt)
389
        if len(self.current.exits) > len(directions):
390
            print lang["EXTRAROOMS"] % ", ".join(map(lambda x: x.name, self.current.exits[9:]))
391
        print
392
    do_nea = do_nearby
393
 
394
    def do_go(self, symname):
395
        if not symname:
396
            print lang["EH?"]
397
            return
398
        symbol = configuration.dictionary.get(symname)
399
        if symbol and symbol.type in ("menu", "choices"):
400
            self.current = symbol
401
            if not configuration.is_visible(self.current) and not self.current.frozen():
402
                print lang["SUPPRESSOFF"]
403
                self.suppressions = 0
404
        else:
405
            print lang["NONEXIST"]
406
 
407
    def do_dir(self, dir):
408
        to = self.current.directions.get(dir)
409
        if to:
410
            self.current = to
411
        else:
412
            print lang["NOWAY"]
413
    def do_n(self, dummy): self.do_dir('n')
414
    def do_e(self, dummy): self.do_dir('e')
415
    def do_w(self, dummy): self.do_dir('w')
416
    def do_s(self, dummy): self.do_dir('s')
417
    def do_ne(self, dummy): self.do_dir('ne')
418
    def do_nw(self, dummy): self.do_dir('nw')
419
    def do_se(self, dummy): self.do_dir('se')
420
    def do_sw(self, dummy): self.do_dir('sw')
421
    def do_u(self, dummy): self.do_up(dummy)
422
    def do_d(self, dummy): self.do_dir('dn')
423
 
424
    def do_up(self, dummy):
425
        if self.current == configuration.start:
426
            print lang["GOODBYE"]
427
            raise SystemExit
428
        else:
429
            self.current = self.current.menu
430
 
431
    def do_inventory(self, dummy):
432
        inventory()
433
    do_inv = do_inventory
434
    do_i = do_inventory
435
 
436
    def do_drop(self, line):
437
        global lanternloc, gruestate
438
        if not line:
439
            print lang["EH?"]
440
            return
441
        words = line.lower().split()
442
        if words == ["all"] and self.current.type != "choices":
443
            words = map(lambda x:x.name, filter(lambda x:x.is_logical() and configuration.is_visible(x) and not x.eval(), self.current.items))
444
            if lanternloc == 'user':
445
                words.append(lang["LANTERN"])
446
        for thing in words:
447
            if thing == lang["LANTERN"]:
448
                lanternloc = self.current
449
                gruestate = 1
450
                print lang["LANTERNDROP"]
451
            else:
452
                symbolname = thing.upper()
453
                symbol = configuration.dictionary.get(symbolname)
454
                if not symbol:
455
                    print lang["NOSUCHAS"], symbolname
456
                    continue
457
                elif not symbol.eval():
458
                    print lang["NOHAVE"] % symbolname
459
                    continue
460
                elif symbol.menu.type == "choices":
461
                    if symbol.menu != self.current:
462
                        print lang["NOBUTTON"] % symbolname
463
                    else:
464
                        print lang["TRYPRESS"]
465
                    return
466
                elif symbol.is_logical():
467
                    ok = self.set_symbol(symbol, cml.n)
468
                elif symbol.is_numeric():
469
                    ok = self.set_symbol(symbol, 0)
470
                elif symbol.type == "string":
471
                    ok = self.set_symbol(symbol, "")
472
                if ok:
473
                    print lang["DROPPED"] % symbol.name
474
    do_dro = do_drop
475
 
476
    def do_take(self, line):
477
        global lanternloc
478
        if not line:
479
            print lang["EH?"]
480
            return
481
        words = line.lower().split()
482
        if words == ["all"] and self.current.type != "choices":
483
            words = map(lambda x:x.name, filter(lambda x:x.is_logical() and configuration.is_visible(x) and not x.eval(), self.current.items))
484
            if lanternloc == self.current:
485
                words.append(lang["LANTERN"])
486
        if ("module" in words):
487
            tritval = cml.m
488
            words.remove("module")
489
        else:
490
            tritval = cml.y
491
        for thing in words:
492
            if thing == lang["LANTERN"]:
493
                lanternloc = 'user'
494
                print lang["LANTERNTAKE"]
495
            else:
496
                symbolname = thing.upper()
497
                symbol = configuration.dictionary.get(symbolname)
498
                if not symbol:
499
                    print lang["NOSUCHAS"], symbolname
500
                elif symbol.menu != self.current:
501
                    print lang["NOHERE"] % symbol.name
502
                elif symbol.is_logical():
503
                    if self.set_symbol(symbol, tritval):
504
                        print lang["TAKEN"] % symbol.name
505
                else:
506
                    print lang["USESET"] % symbol.name
507
    do_tak = do_take
508
 
509
    def do_press(self, line):
510
        if not line:
511
            print lang["EH?"]
512
        else:
513
            symbol = configuration.dictionary.get(line)
514
            if not symbol or symbol.menu != self.current:
515
                print lang["NOHERE"] % line
516
            else:
517
                self.set_symbol(symbol, cml.y)
518
    do_pus = do_push = do_pre = do_press
519
 
520
    def do_light(self, dummy):
521
        global gruestate
522
        if lanternloc == 'user':
523
            print lang["GLOW"]
524
            gruestate = 3
525
        else:
526
            print lang["NOHERE"] % lang["LANTERN"]
527
    do_lig = do_light
528
 
529
    def do_set(self, line):
530
        symbol = None
531
        try:
532
            (symname, value) = line.split()
533
            symbol = configuration.dictionary[symname]
534
        except:
535
            print lang["EH?"]
536
        if not symbol:
537
            print lang["NOSUCHAS"], symbol.name
538
        elif symbol.menu != self.current:
539
            print lang["NOHERE"] % symbol.name
540
        elif symbol.menu.type == "choices" or symbol.is_logical():
541
            print lang["CANTDO"]
542
        elif symbol.is_numeric():
543
            self.set_symbol(symbol, int(value))
544
        elif symbol.type == "string":
545
            self.set_symbol(symbol, value)
546
 
547
    def do_xyzzy(self,  dummy):
548
        # Toggle the suppressions flag
549
        configuration.suppressions = not configuration.suppressions
550
        if configuration.suppressions:
551
            print lang["SUPPRESSON"]
552
        else:
553
            print lang["SUPPRESSOFF"]
554
        return 0
555
 
556
    def do_load(self, line):
557
        if not line:
558
            print lang["EH?"]
559
            return
560
        file = string.strip(line)
561
        if file.find(' ') > -1:
562
            (file, option) = file.split(' ')
563
        try:
564
            (changes, errors) = configuration.load(file, freeze=(option == "frozen"))
565
        except IOError:
566
            print lang["LOADFAIL"] % file
567
        else:
568
            if errors:
569
                print errors
570
            print lang["INCCHANGES"] % (changes,file)
571
            if configuration.side_effects:
572
                sys.stdout.write(string.join(configuration.side_effects, "\n") + "\n")
573
    do_loa = do_load
574
 
575
    def do_save(self, line):
576
        if not line:
577
            print lang["EH?"]
578
            return
579
        file = string.strip(line)
580
        failure = configuration.save(file, cml.Baton(lang["SAVESTART"] % file, lang["SAVEEND"]))
581
        if failure:
582
            print failure
583
    do_sav = do_save
584
 
585
    def do_exit(self, dummy):
586
        # Terminate this cmd instance, saving configuration
587
        self.do_s(configfile)
588
        return 1
589
    do_exi = do_exit
590
 
591
    def do_quit(self, line):
592
        # Terminate this cmd instance, not saving configuration
593
        return 1
594
    do_qui = do_quit
595
 
596
    # Debugging commands -- not documented
597
    def do_verbose(self, line):
598
        # Set the debug flag
599
        if not line:
600
            configuration.debug += 1
601
        else:
602
            configuration.debug = int(line)
603
        return 0
604
    do_ver = do_verbose
605
 
606
    def do_examine(self, line):
607
        # Examine the state of a given symbol
608
        symbol = string.strip(line)
609
        if configuration.dictionary.has_key(symbol):
610
            entry = configuration.dictionary[symbol]
611
            print entry
612
            if entry.constraints:
613
                print lang["CONSTRAINTS"]
614
                for wff in entry.constraints:
615
                    print cml.display_expression(wff)
616
            if configuration.is_visible(entry):
617
                print lang["VISIBLE"]
618
            else:
619
                print lang["INVISIBLE"]
620
            help = entry.help()
621
            if help:
622
                print help
623
            else:
624
                print lang["NOHELP"] % (entry.name,)
625
        elif symbol == "lantern":
626
            if lanternloc == "user" or lanternloc == self.current:
627
                print lang["LANTERNHELP"]
628
            else:
629
                print lang["NOHERE"] % lang["LANTERN"]
630
        else:
631
            print lang["NOSUCHAS"], symbol
632
        return 0
633
    do_exa = do_examine
634
 
635
    def emptyline(self):
636
        return 0
637
    def do_commands(self, dummy):
638
        print string.join(map(lambda x: lang[x],
639
                                  ("LHELP", "NHELP", "GHELP", "IHELP",
640
                                   "DHELP", "THELP", "PHELP", "SETHELP",
641
                                   "LDHELP", "SHELP", "XYZZY",
642
                                   "QHELP", "XHELP", "DIRHELP")),
643
                              "\n")
644
    def help_look(self):
645
        print lang["LHELP"]
646
    help_loo = help_look
647
    def help_nearby(self):
648
        print lang["NHELP"]
649
    help_nea = help_nearby
650
    def help_go(self):
651
        print lang["GHELP"]
652
    def help_inventory(self):
653
        print lang["IHELP"]
654
    help_inv = help_inventory
655
    def help_drop(self):
656
        print lang["DHELP"]
657
    help_dro = help_drop
658
    def help_take(self):
659
        print lang["THELP"]
660
    help_tak = help_take
661
    def help_press(self):
662
        print lang["PHELP"]
663
    help_pus = help_push = help_pre = help_press
664
    def help_set(self):
665
        print lang["SETHELP"]
666
    def help_xyzzy(self):
667
        print lang["XYZZY"]
668
    def help_load(self):
669
        print lang["LDHELP"]
670
    help_loa = help_load
671
    def help_save(self):
672
        print lang["SHELP"]
673
    help_sav = help_save
674
    def help_quit(self):
675
        print lang["QHELP"]
676
    help_qui = help_quit
677
    def help_exit(self):
678
        print lang["XHELP"]
679
    help_exi = help_exit
680
    def do_help(self, dummy):
681
        print lang["GENHELP"]
682
    def postcmd(self, stop, dummy):
683
        if stop:
684
            return stop
685
        if self.current != self.last:
686
            newroom(self.current)
687
            visit(self.current, 4 - 3 * (self.current.visits > 1))
688
            self.last = self.current
689
        return None
690
 
691
# Rulebase loading and option processing
692
 
693
def load_system(cmd_options, cmd_arguments):
694
    "Read in the rulebase and handle command-line arguments."
695
    global debug, configfile, configuration
696
    debug = 0;
697
    configfile = None
698
 
699
    if not cmd_arguments:
700
        rulebase = "rules.out"
701
    else:
702
        rulebase = cmd_arguments[0]
703
    try:
704
        open(rulebase, 'rb')
705
    except IOError:
706
        print lang["NOFILE"] % (rulebase,)
707
        raise SystemExit
708
    configuration = cmlsystem.CMLSystem(rulebase)
709
 
710
    process_options(configuration, cmd_options)
711
 
712
    configuration.debug_emit(1, lang["PARAMS"] % (configfile,configuration.prefix))
713
 
714
    # Perhaps the user needs modules enabled initially
715
    if configuration.trit_tie and cml.evaluate(configuration.trit_tie):
716
        configuration.trits_enabled = 1
717
 
718
    # Don't count all these automatically generated settings
719
    # for purposes of figuring out whether we should confirm a quit.
720
    configuration.commits = 0
721
 
722
    return configuration
723
 
724
def process_include(myconfiguration, file, freeze):
725
    "Process a -i or -I inclusion option."
726
    # Failure to find an include file is non-fatal
727
    try:
728
        (changes, errors) = myconfiguration.load(file, freeze)
729
    except IOError:
730
        print lang["LOADFAIL"] % file
731
        return
732
    if errors:
733
        print errors
734
    elif myconfiguration.side_effects:
735
        print lang["SIDEFROM"] % file
736
        sys.stdout.write(string.join(myconfiguration.side_effects, "\n") + "\n")
737
 
738
def process_define(myconfiguration, val, freeze):
739
    "Process a -d=xxx or -D=xxx option."
740
    parts = string.split(val, "=")
741
    sym = parts[0]
742
    if myconfiguration.dictionary.has_key(sym):
743
        sym = myconfiguration.dictionary[sym]
744
    else:
745
        myconfiguration.errout.write(lang["SYMUNKNOWN"] % (`sym`,))
746
        sys.exit(1)
747
    if sym.is_derived():
748
        myconfiguration.debug_emit(1, lang["DERIVED"] % (`sym`,))
749
        sys.exit(1)
750
    elif sym.is_logical():
751
        if len(parts) == 1:
752
            val = 'y'
753
        elif parts[1] == 'y':
754
            val = 'y'
755
        elif parts[1] == 'm':
756
            myconfiguration.trits_enabled = 1
757
            val = 'm'
758
        elif parts[1] == 'n':
759
            val = 'n'
760
    elif len(parts) == 1:
761
        print lang["NOCMDLINE"] % (`sym`,)
762
        sys.exit(1)
763
    else:
764
        val = parts[1]
765
    (ok, effects, violations) = myconfiguration.set_symbol(sym,
766
                                     myconfiguration.value_from_string(sym, val),
767
                                     freeze)
768
    if effects:
769
        print lang["EFFECTS"]
770
        sys.stdout.write(string.join(effects, "\n") + "\n\n")
771
    if not ok:
772
        print lang["ROLLBACK"] % (sym.name, val)
773
        sys.stdout.write(string.join(violations,"\n")+"\n")
774
 
775
def process_options(myconfiguration, options):
776
    # Process command-line options second so they override
777
    global list, configfile, debug, banner
778
    configfile = "config.out"
779
    for (switch, val) in options:
780
        if switch == '-B':
781
            banner = val
782
        elif switch == '-d':
783
            process_define(myconfiguration, val, freeze=0)
784
        elif switch == '-D':
785
            process_define(myconfiguration, val, freeze=1)
786
        elif switch == '-i':
787
            process_include(myconfiguration, val, freeze=0)
788
        elif switch == '-I':
789
            process_include(myconfiguration, val, freeze=1)
790
        elif switch == '-l':
791
            list = 1
792
        elif switch == '-o':
793
            configfile = val
794
        elif switch == '-v':
795
            debug = debug + 1
796
            myconfiguration.debug = myconfiguration.debug + 1
797
        elif switch == '-S':
798
            myconfiguration.suppressions = 0
799
 
800
# Main sequence -- isolated here so we can profile it
801
 
802
def main(options, arguments):
803
    global configuration
804
    try:
805
        myconfiguration = load_system(options, arguments)
806
    except KeyboardInterrupt:
807
        raise SystemExit
808
 
809
    # Set seed for random-number functions
810
    whrandom.seed(int(time.time()) % 256, os.getpid() % 256, 23)
811
    global grafittishuffle
812
    grafittishuffle = shuffle(len(grafitti))
813
 
814
    print lang["WELCOME"] % cml.version
815
    myconfiguration.errout = sys.stdout
816
    advent_menu(configfile, banner).cmdloop()
817
 
818
if __name__ == '__main__':
819
    try:
820
        runopts = "aB:cD:d:h:i:I:lo:P:R:StVvWx"
821
        (options,arguments) = getopt.getopt(sys.argv[1:], runopts)
822
        if os.environ.has_key("CML2OPTIONS"):
823
            (envopts, envargs) = getopt.getopt(
824
                os.environ["CML2OPTIONS"].split(),
825
                runopts)
826
            options = envopts + options
827
    except:
828
        print lang["BADOPTION"]
829
        sys.exit(1)
830
 
831
    for (switch, val) in options:
832
        if switch == "-V":
833
            print "cmladvent", cml.version
834
            raise SystemExit
835
        elif switch == '-P':
836
            proflog = val
837
    try:
838
        import readline
839
    except:
840
        pass
841
 
842
    try:
843
        if proflog:
844
            import profile, pstats
845
            profile.run("main(options, arguments)", proflog)
846
        else:
847
            main(options, arguments)
848
    except KeyboardInterrupt:
849
        #if configuration.commits > 0:
850
        #    print lang["NOTSAVED"]
851
        print lang["ABORTED"]
852
    except "UNSATISFIABLE":
853
        #configuration.save("post.mortem")
854
        print lang["POSTMORTEM"]
855
        raise SystemExit, 1
856
 
857
# That's all, folks!

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.