1 /* File edit.c */
2 /***************************************************************************
3 * Copyright 2003 - Steven Shipway <steve@cheshire.demon.co.uk> *
4 * Put "nospam" in subject to avoid spam filter *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA *
19 * 02111-1307, USA. *
20 ***************************************************************************/
21
22
23 #include <stdlib.h>
24 #include "wand_head.h"
25
26 extern char *playscreen();
27 extern void helpme();
28 extern int inform_me();
29
30 extern int debug_disp;
31 extern char *edit_screen;
32 extern char screen[NOOFROWS][ROWLEN+1];
33 extern char *edit_memory;
34 extern char *memory_end;
35 extern char screen_name[61];
36
37 static char *inst[] = { " O Boulder",
38 " < > Arrows",
39 " ^ Balloon",
40 " : Earth",
41 " ! Landmine",
42 " * Treasure",
43 " / \\ Deflectors",
44 " + Cage",
45 "_ = # Rock (# indestructable)",
46 " T Teleport",
47 " A Arrival (1 max)",
48 " X Exit (always 1)",
49 " @ Start (always 1)",
50 " M Big Monster (1 max)",
51 " S Baby Monster",
52 " - Alternative space",
53 " C Time Capsule",
54 " ~ Thingy",
55 " B Bomb",
56 NULL };
57
58 /*********************************************************
59 * check_legality *
60 * this will check: baby monster vs cage numbers, *
61 * teleport, large monster, *
62 * exit and player numbers, *
63 * hanging boulders/arrows etc *
64 **********************************************************/
check_legality()65 check_legality()
66 {
67 int ercount,cages,hanging,bmons,tele,arrival,you,mons,exits;
68 int x, y;
69 char buf[80];
70 ercount = hanging = cages = bmons = tele = arrival = you = mons = exits = 0;
71
72 move(20,0);
73 addstr("Checking screen legality..."); refresh();
74 for( x = 0 ; x < ROWLEN ; x++)
75 for( y = 0 ; y < NOOFROWS ; y++) {
76 move(y+1,x+1); addch('?'); refresh();
77 switch(screen[y][x]) {
78 case '+': cages++; break;
79 case 'S': bmons++; break;
80 case 'T': tele++; break;
81 case 'A': arrival++; break;
82 case '@': you++; break;
83 case 'M': mons++; break;
84 case 'X': exits++; break;
85 case '-':
86 case ' ': if((screen[y-1][x] == 'O')&&(y>0)) hanging++;
87 if((screen[y+1][x] == '^')&&(y<NOOFROWS)) hanging++;
88 if((screen[y][x-1] == '>')&&(x>0)) hanging++;
89 if((screen[y][x+1] == '<')&&(x<ROWLEN)) hanging++;
90 break;
91 default : break;
92 }
93 move(y+1,x+1); addch(screen[y][x]);
94 }
95 move(20,0); addstr(" ");
96 if(cages != bmons) {
97 ercount++;
98 if( cages < bmons )
99 sprintf(buf,"++++ Warning: %d cage(s), %d baby monster(s).",cages,bmons);
100 else
101 sprintf(buf,"**** Cage imbalance: %d cage(s), %d baby monster(s).",cages,bmons);
102 if(inform_me(buf,1)) return;
103 }
104 if(tele > 1) {
105 ercount++;
106 if(inform_me("++++ Warning: Too many teleports",1)) return;
107 }
108 if(arrival > ((tele>0)?1:0)) {
109 ercount++;
110 if(tele == 0) {
111 if(inform_me("**** No arrivals without teleports.",1)) return;
112 } else if(inform_me("**** Too many arrivals.",1)) return;
113 }
114 if(( arrival == 0 ) && ( tele > 0 )) {
115 ercount++;
116 if(inform_me("**** No arrival for teleport.",1)) return;
117 }
118 if( you != 1 ) {
119 ercount++;
120 if( you == 0 ) {
121 if(inform_me("**** No start position.",1)) return;
122 } else if(inform_me("**** Too many start positions.",1))return;
123 }
124 if( mons > 1 ) {
125 ercount++;
126 if(inform_me("**** Too many monsters.",1))return;
127 }
128 if( exits != 1 ) {
129 ercount++;
130 if( exits == 0 ) {
131 if(inform_me("**** No exit to screen.",1))return;
132 } else if(inform_me("++++ Warning: Too many exits.",1))return;
133 }
134 if( hanging > 0 ) {
135 sprintf(buf,"++++ Warning: %d hanging boulders/arrows/balloons.",hanging);
136 if(inform_me(buf,1)) return;
137 }
138 ercount += hanging;
139 move(19,0);
140 if( ercount == 0 ) inform_me("---- Screen OK.",0);
141 else {
142 sprintf(buf,"---- Total errors: %d",ercount);
143 inform_me(buf,0);
144 }
145 refresh();
146 }
147
148 /**************************************************************
149 * readstring *
150 ***************************************************************/
readstring(str,size)151 void readstring(str,size)
152 char *str;
153 int size;
154 {
155 int count = 0;
156 char ch;
157 for(;;) {
158 ch = getch();
159 if( ch == '\n' ) {
160 *str = '\0';
161 break;
162 }
163 if(( ch == '\010') || ( ch == '\177' )) {
164 if(count == 0)
165 continue;
166 str--; count--;
167 addstr("\b \b");
168 refresh();
169 continue;
170 }
171 if(count == size) {
172 printf("\007");
173 continue;
174 }
175 addch(ch);
176 *str = ch;
177 str++; count++;
178 refresh();
179 }
180 }
181
clearbottom()182 clearbottom()
183 {
184 move(20,0);
185 addstr(" \n");
186 addstr(" \n");
187 addstr(" ");
188 }
189
190 /*****************************************
191 * instruct *
192 * Print instructions around the screen *
193 ******************************************/
instruct()194 void instruct()
195 {
196 int loop;
197 for(loop = 0; inst[loop] ; loop++)
198 {
199 move(loop,45);
200 addstr(inst[loop]);
201 }
202 move(21,0);
203 addstr("c: change name, m: change moves, q: save and exit, n/p: play game\n");
204 addstr("Press '?' for full editor instructions. Use wanderer keys to move.");
205 }
206
207
208 /************************************************
209 * noins *
210 *************************************************/
noins()211 void noins()
212 {
213 int loop;
214 for(loop =0; inst[loop] ; loop++)
215 {
216 move(loop,45);
217 addstr(" ");
218 }
219 clearbottom();
220 }
221
222 /********************************
223 * screen_save *
224 * save and restore screen data *
225 *********************************/
screen_save(maxmoves)226 screen_save(maxmoves)
227 int maxmoves;
228 {
229 char file[90];
230 char *oldname;
231 int y;
232
233 clearbottom();
234 move(20,0);
235 addstr("Filename to write to? :");
236 if(edit_screen)
237 addstr(edit_screen);
238 else
239 addstr("./screen");
240 move(20,23); refresh();
241 addstr(" "); move(20,23);
242 readstring(file,89);
243 move(20,0);
244 addstr(" "); refresh();
245 oldname = edit_screen;
246 if( file[0] ) edit_screen = file;
247 for(y = 0; y<=NOOFROWS;y++) /* make sure screen written */
248 if(screen[y][ROWLEN-1] == ' ') /* correctly... */
249 screen[y][ROWLEN-1] = '-';
250 wscreen(0,maxmoves);
251 for(y = 0; y<=NOOFROWS;y++)
252 if(screen[y][ROWLEN-1] == '-')
253 screen[y][ROWLEN-1] = ' ';
254 edit_screen = oldname;
255 }
256
257 /*********************************************
258 * screen_read *
259 **********************************************/
screen_read(maxmoves)260 screen_read(maxmoves)
261 int *maxmoves;
262 {
263 static char file[90];
264 int y;
265
266 clearbottom();
267 move(20,0);
268 addstr("Filename to read from? :");
269 addstr("Forget it");
270 move(20,24); refresh();
271 addstr(" "); move(20,24);
272 readstring(file,89);
273 move(20,0);
274 addstr(" "); refresh();
275 if( ! file[0] ) return;
276 edit_screen = file;
277 rscreen(0,maxmoves);
278 for(y = 0; y<=NOOFROWS;y++)
279 if(screen[y][ROWLEN-1] == '-')
280 screen[y][ROWLEN-1] = ' ';
281 }
282
283
284 /*************************************
285 * edit_save *
286 * save and restore edit memory data *
287 **************************************/
edit_save()288 edit_save()
289 {
290 char file[90];
291 int i = 0,fd;
292
293 clearbottom();
294 move(20,0);
295 addstr("Filename to save? :"); refresh();
296 readstring(file,89);
297 move(20,0); addstr(" "); refresh();
298 if(( fd = open(file,O_WRONLY|O_CREAT|O_TRUNC,0644)) == -1 ) {
299 inform_me("File cannot be opened for writing.",0);
300 } else {
301 i = write(fd, edit_memory, (int)(memory_end - edit_memory));
302 if( i < 0 ) inform_me("Write error on file.",0);
303 }
304 instruct();
305 }
306
307 /*******************************************
308 * edit_restore *
309 ********************************************/
edit_restore()310 edit_restore()
311 {
312 char file[90];
313 int i = 0,fd;
314
315 clearbottom();
316 move(20,0);
317 addstr("Filename to load? :"); refresh();
318 readstring(file,89);
319 move(20,0); addstr(" "); refresh();
320 move(19,0);
321 if(( fd = open(file,O_RDONLY)) == -1 ) {
322 inform_me("File cannot be opened for reading.",0);
323 } else {
324 i = read(fd, edit_memory, EMSIZE);
325 if( i < 0 ) inform_me("Read error on file.",0);
326 if( i == 0 ) inform_me("File empty.",0);
327 if( i > 0 ) {
328 sprintf(file,"Read in %d moves.",i);
329 inform_me(file,0);
330 memory_end = edit_memory + i;
331 }
332 }
333 instruct();
334 }
335
336 /*************************
337 * editscreen *
338 * Actual edit function *
339 **************************/
editscreen(num,score,bell,maxmoves,keys)340 void editscreen(num,score,bell,maxmoves,keys)
341 int num;
342 int maxmoves, *bell, *score;
343 char keys[10];
344 {
345 int mmbkup,x,y,sx=0,sy=0,quit=0,nx,ny,nosave =0;
346 char (*frow)[ROWLEN+1] = screen,
347 ch;
348 char buffer[50];
349 char *howdead;
350 char *storage;
351
352 if((storage = (char *) malloc(sizeof(screen)))== NULL) {
353 addstr("OOps... cant malloc a backup screen!\n\n");
354 return;
355 }
356
357 for(x=0;x<=ROWLEN;x++)
358 for(y=0;y<NOOFROWS;y++)
359 {
360 if(screen[y][x] == '@')
361 {
362 sx = x;
363 sy = y;
364 }
365 if(screen[y][x] == '-')
366 screen[y][x] = ' ';
367 };
368 x=sx;
369 y=sy;
370 if(maxmoves != 0)
371 (void) sprintf(buffer,"Moves : %d ",maxmoves);
372 else
373 (void) strcpy(buffer,"Moves : Unlimited");
374 debug_disp=1;
375 map(frow);
376 move(18,0);
377 addstr(buffer);
378 move(19,0);
379 addstr(" ");
380 move(19,0);
381 addstr("Name : ");
382 addstr(screen_name);
383
384 /* ACTUAL EDIT FUNCTION */
385
386 instruct();
387 /* HERE */
388 /* Beginning of long while loop */
389 while(!quit)
390 {
391 move(y+1,x+1);
392 refresh();
393 ch = (char)getchar();
394
395 nx=x;
396 ny=y;
397
398 if(ch == keys[3]||ch == keys[2]||ch == keys[1]||ch == keys[0])
399 {
400 if(ch == keys[3])
401 nx++;
402 if(ch == keys[2])
403 nx--;
404 if(ch == keys[1])
405 ny++;
406 if(ch == keys[0])
407 ny--;
408 }
409 else if(ch == 'q')
410 {
411 clearbottom();
412 break;
413 }
414 else if(ch == 'x')
415 {
416 clearbottom();
417 move(20,0);
418 addstr("You will lose any changes made this session - are you sure? (y/n)");
419 refresh();
420 ch = getch();
421 if(ch != 'y')
422 {
423 noins();
424 instruct();
425 refresh();
426 }
427 else
428 {
429 nosave = 1;
430 addstr("\n");
431 refresh();
432 break;
433 }
434 }
435 else if(ch == 'm') /* change to number of moves for the screen */
436 {
437 clearbottom();
438 move(21,0);
439 addstr("How many moves for this screen? :");
440 refresh();echo();
441 scanf("%d",&maxmoves);noecho();
442 if(maxmoves < 0 ) maxmoves = 0;
443 if(maxmoves != 0)
444 (void) sprintf(buffer,"Moves : %d ",maxmoves);
445 else
446 (void) strcpy(buffer,"Moves : Unlimited ");
447 instruct();
448 move(18,0);
449 addstr(buffer);
450 refresh(); /* for some reason, this seems to add a '.' to */
451 /* the map... Ive no idea why yet... */
452 }
453 else if(ch == 'c') { /* change name */
454 clearbottom();
455 move(21,0);
456 addstr("New name: ");
457 refresh();
458 readstring(screen_name,58);
459 screen_name[61] = '\0';
460 instruct();
461 move(19,0);
462 addstr(" ");
463 move(19,0);
464 addstr("Name : ");
465 addstr(screen_name);
466 refresh();
467 }
468 else if(ch == 'p' || ch == 'n') /* play the game (test) */
469 {
470 noins();
471 mmbkup = maxmoves;
472 bcopy(screen,storage,sizeof(screen));
473 if(ch == 'p')
474 {
475 debug_disp = 0;
476 clear();
477 }
478 *score = 0;
479 howdead = playscreen(&num,score,bell,maxmoves,keys);
480 move(20,0);
481 if(howdead!=0)
482 addstr(howdead);
483 else
484 addstr("DONE!");
485 printw("; hit any key to continue\n");
486 refresh();
487 ch = (char)getchar();
488 clear();
489 bcopy(storage,screen,sizeof(screen));
490 maxmoves = mmbkup;
491 debug_disp = 1;
492 map(frow);
493 if(maxmoves != 0)
494 (void) sprintf(buffer,"Moves : %d \n",maxmoves);
495 else
496 (void) strcpy(buffer,"Moves : Unlimited\n");
497 move(18,0);
498 addstr(buffer);
499 addstr("Name : ");
500 addstr(screen_name);
501 instruct();
502 }
503 else if(ch == 18) { /* ctrl r -- read memory data */
504 edit_restore();
505 }
506 else if( ch == 23) { /* ctrl w -- write memory data */
507 edit_save();
508 }
509 else if( ch == 7 ) { /* ctrl g -- read screen */
510 screen_read(&maxmoves);
511 map(frow);
512 instruct();
513 }
514 else if( ch == 16 ) { /* ctrl p -- write screen */
515 screen_save(maxmoves);
516 instruct();
517 }
518 else if( ch == 12 ) { /* ctrl l -- redraw screen */
519 clear();
520 map(frow);
521 if(maxmoves != 0)
522 (void) sprintf(buffer,"Moves : %d \n",maxmoves);
523 else
524 (void) strcpy(buffer,"Moves : Unlimited\n");
525 move(18,0);
526 addstr(buffer);
527 addstr("Name : ");
528 addstr(screen_name);
529 instruct();
530 }
531 else if( ch == 'L' ) {
532 clearbottom();
533 check_legality();
534 instruct();
535 }
536 else if(ch == '?' ) {
537 helpme(0);
538 if(maxmoves != 0)
539 (void) sprintf(buffer,"Moves : %d \n",maxmoves);
540 else
541 (void) strcpy(buffer,"Moves : Unlimited\n");
542 map(frow);
543 }
544 else if((ch == 127)||(ch == 8)) { /* delete key */
545 if(--nx < 0)
546 {
547 nx = ROWLEN -1;
548 if(--ny < 0 ) ny = NOOFROWS -1;
549 }
550 screen[ny][nx] = ' ';
551 move(ny+1,nx+1);
552 addch(' ');
553 }
554 else
555 {
556 if(ch >= 'a' && ch <= 'z') ch = ch - 'a' + 'A';
557 if(ch == '"') ch = (char)getchar();
558 if( ! (ch < ' ') )
559 {
560 screen[y][x] = ch;
561 move(y+1,x+1);
562 addch(ch);
563 nx++;
564 }
565 }
566 if(nx < 0)
567 {
568 nx = ROWLEN-1;
569 ny--;
570 }
571 if(nx >= ROWLEN)
572 {
573 nx = 0;
574 ny++;
575 }
576 if(ny < 0) ny = NOOFROWS-1;
577 if(ny >= NOOFROWS) ny = 0;
578 move(ny+1,nx+1);
579 x=nx;
580 y=ny;
581 }
582 /* End of while loop */
583
584 noins();
585 move(20,0);
586 refresh();
587
588 if(! nosave)
589 {
590 for(y = 0; y<=NOOFROWS;y++) /* certain editors - eg ded - have a */
591 /* habit of truncating trailing spaces*/
592 /* so this should stop them! */
593 if(screen[y][ROWLEN-1] == ' ')
594 screen[y][ROWLEN-1] = '-';
595 wscreen(num,maxmoves);
596 }
597 }
598