OSDN Git Service

import nethack-3.6.0
[jnethack/source.git] / sys / be / bemain.c
1 /* NetHack 3.6  bemain.c        $NHDT-Date: 1447844549 2015/11/18 11:02:29 $  $NHDT-Branch: master $:$NHDT-Revision: 1.18 $ */
2 /* Copyright (c) Dean Luick, 1996. */
3 /* NetHack may be freely redistributed.  See license for details. */
4
5 #include "hack.h"
6 #include "dlb.h"
7 #include <fcntl.h>
8
9 static void whoami(void);
10 static void process_options(int argc, char **argv);
11 static void chdirx(const char *dir);
12 static void getlock(void);
13
14 #ifdef __begui__
15 #define MAIN nhmain
16 int nhmain(int argc, char **argv);
17 #else
18 #define MAIN main
19 #endif
20
21 int
22 MAIN(int argc, char **argv)
23 {
24     int fd;
25     char *dir;
26     boolean resuming = FALSE; /* assume new game */
27
28     sys_early_init();
29
30     dir = nh_getenv("NETHACKDIR");
31     if (!dir)
32         dir = nh_getenv("HACKDIR");
33
34     choose_windows(DEFAULT_WINDOW_SYS);
35     chdirx(dir);
36     initoptions();
37
38     init_nhwindows(&argc, argv);
39     whoami();
40
41     /*
42      * It seems you really want to play.
43      */
44     u.uhp = 1;                   /* prevent RIP on early quits */
45     process_options(argc, argv); /* command line options */
46
47     set_playmode(); /* sets plname to "wizard" for wizard mode */
48     /* strip role,race,&c suffix; calls askname() if plname[] is empty
49        or holds a generic user name like "player" or "games" */
50     plnamesuffix();
51     /* unlike Unix where the game might be invoked with a script
52        which forces a particular character name for each player
53        using a shared account, we always allow player to rename
54        the character during role/race/&c selection */
55     iflags.renameallowed = TRUE;
56
57     getlock();
58
59     dlb_init(); /* must be before newgame() */
60
61     /*
62      * Initialize the vision system.  This must be before mklev() on a
63      * new game or before a level restore on a saved game.
64      */
65     vision_init();
66
67     display_gamewindows();
68
69     /*
70      * First, try to find and restore a save file for specified character.
71      * We'll return here if new game player_selection() renames the hero.
72      */
73 attempt_restore:
74     if ((fd = restore_saved_game()) >= 0) {
75 #ifdef NEWS
76         if (iflags.news) {
77             display_file(NEWS, FALSE);
78             iflags.news = FALSE; /* in case dorecover() fails */
79         }
80 #endif
81         pline("Restoring save file...");
82         mark_synch(); /* flush output */
83         if (dorecover(fd)) {
84             resuming = TRUE; /* not starting new game */
85             if (discover)
86                 You("are in non-scoring discovery mode.");
87             if (discover || wizard) {
88                 if (yn("Do you want to keep the save file?") == 'n')
89                     (void) delete_savefile();
90                 else {
91                     nh_compress(fqname(SAVEF, SAVEPREFIX, 0));
92                 }
93             }
94         }
95     }
96
97     if (!resuming) {
98         /* new game:  start by choosing role, race, etc;
99            player might change the hero's name while doing that,
100            in which case we try to restore under the new name
101            and skip selection this time if that didn't succeed */
102         if (!iflags.renameinprogress) {
103             player_selection();
104             if (iflags.renameinprogress) {
105                 /* player has renamed the hero while selecting role;
106                    discard current lock file and create another for
107                    the new character name */
108                 delete_levelfile(0); /* remove empty lock file */
109                 getlock();
110                 goto attempt_restore;
111             }
112         }
113         newgame();
114         if (discover)
115             You("are in non-scoring discovery mode.");
116     }
117
118     moveloop(resuming);
119     return 0;
120 }
121
122 static void
123 whoami(void)
124 {
125     /*
126      * Who am i? Algorithm: 1. Use name as specified in NETHACKOPTIONS
127      *                      2. Use $USER or $LOGNAME        (if 1. fails)
128      * The resulting name is overridden by command line options.
129      * If everything fails, or if the resulting name is some generic
130      * account like "games", "play", "player", "hack" then eventually
131      * we'll ask him.
132      */
133     char *s;
134
135     if (*plname)
136         return;
137     if (s = nh_getenv("USER")) {
138         (void) strncpy(plname, s, sizeof(plname) - 1);
139         return;
140     }
141     if (s = nh_getenv("LOGNAME")) {
142         (void) strncpy(plname, s, sizeof(plname) - 1);
143         return;
144     }
145 }
146
147 /* normalize file name - we don't like .'s, /'s, spaces */
148 void
149 regularize(char *s)
150 {
151     register char *lp;
152
153     while ((lp = strchr(s, '.')) || (lp = strchr(s, '/'))
154            || (lp = strchr(s, ' ')))
155         *lp = '_';
156 }
157
158 static void
159 process_options(int argc, char **argv)
160 {
161     int i;
162
163     while (argc > 1 && argv[1][0] == '-') {
164         argv++;
165         argc--;
166         switch (argv[0][1]) {
167         case 'D':
168             wizard = TRUE, discover = FALSE;
169             break;
170         case 'X':
171             discover = TRUE, wizard = FALSE;
172             break;
173 #ifdef NEWS
174         case 'n':
175             iflags.news = FALSE;
176             break;
177 #endif
178         case 'u':
179             if (argv[0][2])
180                 (void) strncpy(plname, argv[0] + 2, sizeof(plname) - 1);
181             else if (argc > 1) {
182                 argc--;
183                 argv++;
184                 (void) strncpy(plname, argv[0], sizeof(plname) - 1);
185             } else
186                 raw_print("Player name expected after -u");
187             break;
188         case 'p': /* profession (role) */
189             if (argv[0][2]) {
190                 if ((i = str2role(&argv[0][2])) >= 0)
191                     flags.initrole = i;
192             } else if (argc > 1) {
193                 argc--;
194                 argv++;
195                 if ((i = str2role(argv[0])) >= 0)
196                     flags.initrole = i;
197             }
198             break;
199         case 'r': /* race */
200             if (argv[0][2]) {
201                 if ((i = str2race(&argv[0][2])) >= 0)
202                     flags.initrace = i;
203             } else if (argc > 1) {
204                 argc--;
205                 argv++;
206                 if ((i = str2race(argv[0])) >= 0)
207                     flags.initrace = i;
208             }
209             break;
210         case '@':
211             flags.randomall = 1;
212             break;
213         default:
214             raw_printf("Unknown option: %s", *argv);
215             break;
216         }
217     }
218 }
219
220 static void
221 chdirx(const char *dir)
222 {
223     if (!dir)
224         dir = HACKDIR;
225
226     if (chdir(dir) < 0)
227         error("Cannot chdir to %s.", dir);
228
229     /* Warn the player if we can't write the record file */
230     /* perhaps we should also test whether . is writable */
231     check_recordfile(dir);
232 }
233
234 void
235 getlock(void)
236 {
237     int fd;
238
239     Sprintf(lock, "%d%s", getuid(), plname);
240     regularize(lock);
241     set_levelfile_name(lock, 0);
242     fd = creat(lock, FCMASK);
243     if (fd == -1) {
244         error("cannot creat lock file.");
245     } else {
246         if (write(fd, (genericptr_t) &hackpid, sizeof(hackpid))
247             != sizeof(hackpid)) {
248             error("cannot write lock");
249         }
250         if (close(fd) == -1) {
251             error("cannot close lock");
252         }
253     }
254 }
255
256 /* validate wizard mode if player has requested access to it */
257 boolean
258 authorize_wizard_mode()
259 {
260     /* other ports validate user name or character name here */
261     return TRUE;
262 }
263
264 #ifndef __begui__
265 /*
266  * If we are not using the Be GUI, then just exit -- we don't need to
267  * do anything extra.
268  */
269 void nethack_exit(int status);
270
271 void
272 nethack_exit(int status)
273 {
274     exit(status);
275 }
276 #endif /* !__begui__ */
277
278 /*bemain.c*/