1 #include <stdio.h>
2 #include <string.h>
3 
4 #include "handwave.h"
5 #include "spelllist.h"
6 
7 struct maingame {
8     int ignorestuff;
9 };
10 
PrintMsg(msg,gameval,rock)11 static void PrintMsg(msg, gameval, rock)
12 char *msg;
13 game *gameval;
14 struct maingame *rock;
15 {
16     if (msg) {
17 	printf("*: ");
18 	fputs(msg, stdout);
19     }
20 }
21 
PrintMsg2(person1,msg1,msgelse,gameval,rock)22 static void PrintMsg2(person1, msg1, msgelse, gameval, rock)
23 int person1;
24 char *msg1, *msgelse;
25 game *gameval;
26 struct maingame *rock;
27 {
28     if (msg1) {
29 	printf("%d: ", person1);
30 	fputs(msg1, stdout);
31     }
32     if (msgelse) {
33 	printf("~%d: ", person1);
34 	fputs(msgelse, stdout);
35     }
36 }
37 
PrintMsg3(person1,person2,msg1,msg2,msgelse,gameval,rock)38 static void PrintMsg3(person1, person2, msg1, msg2, msgelse, gameval, rock)
39 int person1, person2;
40 char *msg1, *msg2, *msgelse;
41 game *gameval;
42 struct maingame *rock;
43 {
44     if (msg1) {
45 	printf("%d: ", person1);
46 	fputs(msg1, stdout);
47     }
48     if (msg2) {
49 	printf("%d: ", person2);
50 	fputs(msg2, stdout);
51     }
52     if (msgelse) {
53 	printf("~%d/~%d: ", person1, person2);
54 	fputs(msgelse, stdout);
55     }
56 }
57 
Queries(numqueries,qlist,gameval,rock)58 static void Queries(numqueries, qlist, gameval, rock)
59 int numqueries;
60 struct query qlist[];
61 game *gameval;
62 struct maingame *rock;
63 {
64     int ix, jx, attnum, spellnum;
65     int res;
66     char inbuf[256];
67     char outbuf[512];
68     static int targetlist[256];
69     static char *targetnamelist[256];
70     int numtargs, targnum;
71 
72     int *hlist;
73     char *ques, *handage;
74 
75     for (ix=0; ix<numqueries; ix++) {
76 	switch (qlist[ix].qtype) {
77 	    case Qu_NoQuery:
78 		/*printf("ERROR: got NoQuery\n");*/
79 		break;
80 	    case Qu_SetOffDelay:
81 		printf(
82 "%d: Do you want to release the %s from the Delayed Effect?\n (0:no, 1:yes): ",
83 				qlist[ix].player,
84 				spelllist[(int)qlist[ix].rock].name);
85 		while (1) {
86 		    fgets(inbuf, 256, stdin);
87 		    res = atol(inbuf);
88 		    if (res!=0 && res!=1) {
89 			printf(" [Please enter 0 or 1]: ");
90 		    }
91 		    else
92 			break;
93 		}
94 		qlist[ix].answer = res;
95 		break;
96 	    case Qu_LeftHand:
97 	    case Qu_RightHand:
98 		if (qlist[ix].qtype==Qu_LeftHand)
99 		    ques = "What spell do you want to cast with your left hand?";
100 		else
101 		    ques = "What spell do you want to cast with your right hand?";
102 		hlist = (int *)qlist[ix].rock;
103 		printf("%d: %s\n (", qlist[ix].player, ques);
104 		for (jx=0; jx<hlist[0]; jx++) {
105 		    spellnum = hlist[jx+1];
106 		    printf("%d: %s%s%s", jx, spelllist[spellnum & (~QuVal_Hand_Both)].name,
107 			   ((spellnum & QuVal_Hand_Both) ? " [both hands]" : ""),
108 			   (jx+1==hlist[0]) ? "): " : ", ");
109 		}
110 		while (1) {
111 		    fgets(inbuf, 256, stdin);
112 		    res = atol(inbuf);
113 		    if (res<0 || res>=hlist[0]) {
114 			printf(" [Please enter a number from 0 to %d]: ", hlist[0]-1);
115 		    }
116 		    else
117 			break;
118 		}
119 		qlist[ix].answer = res;
120 		break;
121 	    case Qu_ElementalType:
122 		printf(
123 "%d: Which type of elemental do you want to summon?\n (0:fire, 1:ice): ",
124 				qlist[ix].player);
125 		while (1) {
126 		    fgets(inbuf, 256, stdin);
127 		    res = atol(inbuf);
128 		    if (res!=0 && res!=1) {
129 			printf(" [Please enter 0 or 1]: ");
130 		    }
131 		    else
132 			break;
133 		}
134 		qlist[ix].answer = res;
135 		break;
136 	    case Qu_ParalysisHand:
137 		printf(
138 "%d: Which of %s's hands do you want to paralyze?\n (0:left, 1:right): ",
139 				qlist[ix].player,
140 				NameOfBeing(gameval, QuVal_Target_Wizard,
141 				qlist[ix].rock));
142 		while (1) {
143 		    fgets(inbuf, 256, stdin);
144 		    res = atol(inbuf);
145 		    if (res!=0 && res!=1) {
146 			printf(" [Please enter 0 or 1]: ");
147 		    }
148 		    else
149 			break;
150 		}
151 		qlist[ix].answer = res;
152 		break;
153 	    case Qu_CharmHand:
154 		printf(
155 "%d: Which of %s's hands do you want to charm?\n (0:left, 1:right): ",
156 				qlist[ix].player,
157 				NameOfBeing(gameval, QuVal_Target_Wizard,
158 				qlist[ix].rock));
159 		while (1) {
160 		    fgets(inbuf, 256, stdin);
161 		    res = atol(inbuf);
162 		    if (res!=0 && res!=1) {
163 			printf(" [Please enter 0 or 1]: ");
164 		    }
165 		    else
166 			break;
167 		}
168 		qlist[ix].answer = res;
169 		break;
170 	    case Qu_CharmGesture:
171 		jx = (int)(qlist[ix].rock);
172 		if (jx >= 128) {
173 		    spellnum = jx - 128;
174 		    jx = 1;
175 		}
176 		else {
177 		    spellnum = jx;
178 		    jx = 0;
179 		}
180 		printf(
181 "%d: What gesture do you want %s's %s hand to make?\n (enter a letter): ",
182 				qlist[ix].player,
183 				NameOfBeing(gameval, QuVal_Target_Wizard,
184 				spellnum), (jx?"right":"left"));
185 		while (1) {
186 		    fgets(inbuf, 256, stdin);
187 		    if (inbuf[0]=='\0' || inbuf[0]=='\n') {
188 			printf(" [Please enter a letter]: ");
189 		    }
190 		    else {
191 			res = cheap_translate(inbuf[0]);
192 			break;
193 		    }
194 		}
195 		qlist[ix].answer = res;
196 		break;
197 	    case Qu_MonsterTarget:
198 		jx = (int)(qlist[ix].rock);
199 		attnum = jx / 256;
200 		spellnum = jx % 256;
201 		switch (attnum) {
202 		    case 1:
203 			sprintf(outbuf, "Whom do you want %s to attack?",
204 					NameOfBeing(gameval,
205 					QuVal_Target_Creature, spellnum));
206 			break;
207 		    case 2:
208 			sprintf(outbuf, "Whom do you want %s's first attack to be at?",
209 					NameOfBeing(gameval,
210 					QuVal_Target_Creature, spellnum));
211 			break;
212 		    case 3:
213 			sprintf(outbuf, "Whom do you want %s's second attack to be at?",
214 					NameOfBeing(gameval,
215 					QuVal_Target_Creature, spellnum));
216 			break;
217 		    default:
218 			sprintf(outbuf, "ERROR: Query about %d (%d)", spellnum, attnum);
219 			break;
220 		}
221 		printf("%d: %s\n", qlist[ix].player, outbuf);
222 		targnum = 0;
223 		targetlist[targnum] = 0;
224 		targetnamelist[targnum] = "nobody";
225 		targnum++;
226 		numtargs = NumberOfTargets(gameval, QuVal_Target_Wizard);
227 		for (jx=0; jx<numtargs; jx++) {
228 		    targetlist[targnum] = jx | QuVal_Target_Wizard;
229 		    targetnamelist[targnum] = NameOfTarget(gameval,
230 				QuVal_Target_Wizard, jx);
231 		    targnum++;
232 		}
233 		numtargs = NumberOfTargets(gameval, QuVal_Target_Creature);
234 		for (jx=0; jx<numtargs; jx++) {
235 		    targetlist[targnum] = jx | QuVal_Target_Creature;
236 		    targetnamelist[targnum] = NameOfTarget(gameval,
237 				QuVal_Target_Creature, jx);
238 		    targnum++;
239 		}
240 		numtargs = targnum;
241 		if (numtargs==0)
242 		    printf("ERROR: No targets available!\n");
243 		else {
244 		    printf(" [");
245 		    for (jx=0; jx<numtargs; jx++) {
246 			printf("%d: %s%s", jx, targetnamelist[jx],
247 					((jx<numtargs-1)?", ":""));
248 		    }
249 		    printf("]: ");
250 		    while (1) {
251 			fgets(inbuf, 256, stdin);
252 			res = atol(inbuf);
253 			if (res<0 || res>=numtargs) {
254 			    printf(" [Please enter a number from 0 to %d]: ",
255 					numtargs-1);
256 			}
257 			else
258 			    break;
259 		    }
260 		    qlist[ix].answer = targetlist[res];
261 		}
262 		break;
263 	    case Qu_WhichToDelay:
264 	    case Qu_WhichToPerm:
265 		if (qlist[ix].qtype == Qu_WhichToDelay)
266 		    printf("%d: Which spell do you want to delay?\n",
267 				qlist[ix].player);
268 		else
269 		    printf("%d: Which spell do you want to make permanent?\n",
270 				qlist[ix].player);
271 
272 		hlist = (int *)qlist[ix].rock;
273 		printf(" [");
274 		for (jx=0; hlist[jx]!=(-1); jx++) {
275 		    printf("%s%d: %s", ((jx)?", ":""), jx, spelllist[hlist[jx]].name);
276 		}
277 		numtargs = jx;
278 		printf("]: ");
279 		while (1) {
280 		    fgets(inbuf, 256, stdin);
281 		    res = atol(inbuf);
282 		    if (res<0 || res>=numtargs) {
283 			printf(" [Please enter a number from 0 to %d]: ", numtargs-1);
284 		    }
285 		    else
286 			break;
287 		}
288 		qlist[ix].answer = res;
289 		break;
290 	    case Qu_TargetBeing:
291 	    case Qu_TargetBeingNone:
292 	    case Qu_TargetWizard:
293 	    case Qu_TargetWizardNone:
294 	    case Qu_TargetRaiseDead:
295 		jx = (int)(qlist[ix].rock);
296 		spellnum = jx & (~QuVal_Hand_MASK);
297 		if (jx & QuVal_Hand_Left)
298 		    handage = "with your left hand";
299 		else if (jx & QuVal_Hand_Right)
300 		    handage = "with your right hand";
301 		else if (jx & QuVal_Hand_Both)
302 		    handage = "with both hands";
303 		else
304 		    handage = "from the Delayed Effect";
305 		if (spellnum==SP__STAB)
306 		    sprintf(outbuf, "Who do you want to stab at (%s)?", handage);
307 		else
308 		    sprintf(outbuf, "Who do you want to cast %s at (%s)?",
309 				spelllist[spellnum].name, handage);
310 		printf("%d: %s\n", qlist[ix].player, outbuf);
311 		targnum = 0;
312 		if (qlist[ix].qtype==Qu_TargetBeingNone ||
313 				qlist[ix].qtype==Qu_TargetWizardNone) {
314 		    targetlist[targnum] = 0;
315 		    targetnamelist[targnum] = "nobody";
316 		    targnum++;
317 		}
318 		numtargs = NumberOfTargets(gameval, QuVal_Target_Wizard);
319 		for (jx=0; jx<numtargs; jx++) {
320 		    targetlist[targnum] = jx | QuVal_Target_Wizard;
321 		    targetnamelist[targnum] = NameOfTarget(gameval,
322 				QuVal_Target_Wizard, jx);
323 		    targnum++;
324 		}
325 		if (qlist[ix].qtype==Qu_TargetBeing ||
326 				qlist[ix].qtype==Qu_TargetBeingNone ||
327 				qlist[ix].qtype==Qu_TargetRaiseDead) {
328 		    numtargs = NumberOfTargets(gameval, QuVal_Target_Creature);
329 		    for (jx=0; jx<numtargs; jx++) {
330 			targetlist[targnum] = jx | QuVal_Target_Creature;
331 			targetnamelist[targnum] = NameOfTarget(gameval,
332 					QuVal_Target_Creature, jx);
333 			targnum++;
334 		    }
335 		}
336 		if (qlist[ix].qtype==Qu_TargetRaiseDead) {
337 		    numtargs = NumberOfTargets(gameval, QuVal_Target_Corpse);
338 		    for (jx=0; jx<numtargs; jx++) {
339 			targetlist[targnum] = jx | QuVal_Target_Corpse;
340 			targetnamelist[targnum] = NameOfTarget(gameval,
341 					QuVal_Target_Corpse, jx);
342 			targnum++;
343 		    }
344 		}
345 		numtargs = targnum;
346 		if (numtargs==0)
347 		    printf("ERROR: No targets available!\n");
348 		else {
349 		    printf(" [");
350 		    for (jx=0; jx<numtargs; jx++) {
351 			printf("%d: %s%s", jx, targetnamelist[jx], ((jx<numtargs-1)?",
352 					":""));
353 		    }
354 		    printf("]: ");
355 		    while (1) {
356 			fgets(inbuf, 256, stdin);
357 			res = atol(inbuf);
358 			if (res<0 || res>=numtargs) {
359 			    printf(" [Please enter a number from 0 to %d]: ",
360 					numtargs-1);
361 			}
362 			else
363 			    break;
364 		    }
365 		    qlist[ix].answer = targetlist[res];
366 		}
367 		break;
368 
369 	    default:
370 		printf("ERROR: Unknown query type %d!\n", qlist[ix].qtype);
371 		break;
372 	}
373     }
374 }
375 
cheap_translate(ch)376 int cheap_translate(ch)
377 char ch;
378 {
379     switch (ch) {
380 	case 'p':
381 	case 'P':
382 	    return Gesture_PALM;
383 	case 'f':
384 	case 'F':
385 	    return Gesture_FINGERS;
386 	case 'd':
387 	case 'D':
388 	    return Gesture_DIGIT;
389 	case 's':
390 	case 'S':
391 	    return Gesture_SNAP;
392 	case 'c':
393 	case 'C':
394 	    return Gesture_CLAPHALF;
395 	case 'w':
396 	case 'W':
397 	    return Gesture_WAVE;
398 	case 'k':
399 	case 'K':
400 	    return Gesture_KNIFE;
401 	case ' ':
402 	case 'n':
403 	case 'N':
404 	default:
405 	    return Gesture_NOTHING;
406     }
407 }
408 
show_beings(gameval)409 void show_beings(gameval)
410 game *gameval;
411 {
412     int ix, max, hp;
413 
414     printf("\n");
415     max = NumberOfBeings(gameval, QuVal_Target_Wizard);
416     for (ix=0; ix<max; ix++) {
417 	hp = HitPointsOfBeing(gameval, QuVal_Target_Wizard, ix);
418 	if (hp>=0)
419 	    printf("%s (%d); ", NameOfBeing(gameval, QuVal_Target_Wizard, ix), hp);
420     }
421     max = NumberOfBeings(gameval, QuVal_Target_Creature);
422     for (ix=0; ix<max; ix++) {
423 	hp = HitPointsOfBeing(gameval, QuVal_Target_Creature, ix);
424 	if (hp>=0)
425 	    printf("%s (%d); ", NameOfBeing(gameval, QuVal_Target_Creature, ix), hp);
426     }
427     printf("\n");
428 }
429 
main(argc,argv)430 main(argc, argv)
431 int argc;
432 char *argv[];
433 {
434     struct interface procs;
435     struct maingame ignorerock;
436     game *gameval;
437     static char *namelist[MAXPLAYERS] = {"Arnold", "Barbara", "Crash"};
438     static int genderlist[MAXPLAYERS] = {Gender_MALE, Gender_FEMALE, Gender_NEUTER};
439     static int movelist[MAXPLAYERS*2];
440     static char inbuf[256];
441     int numplayers, whowon;
442     int ix, val;
443 
444     procs.proc_PrintMsg = PrintMsg;
445     procs.proc_PrintMsg2 = PrintMsg2;
446     procs.proc_PrintMsg3 = PrintMsg3;
447     procs.proc_Queries = Queries;
448 
449     numplayers = 2;
450     if (argc==2 && !strcmp(argv[1], "-3")) {
451 	numplayers = 3;
452     }
453     else if (argc>=2) {
454 	numplayers = 0;
455 	for (ix=1; ix<argc; ix++) {
456 	    char *tmp;
457 	    namelist[numplayers] = argv[ix];
458 	    tmp = index(namelist[numplayers], ':');
459 	    if (!tmp)
460 		genderlist[numplayers] = Gender_MALE;
461 	    else {
462 		switch (*(tmp+1)) {
463 		    case 'f':
464 		    case 'F':
465 			genderlist[numplayers] = Gender_FEMALE;
466 			break;
467 		    case 'n':
468 		    case 'N':
469 			genderlist[numplayers] = Gender_NEUTER;
470 			break;
471 		    case 'x':
472 		    case 'X':
473 			genderlist[numplayers] = Gender_NONE;
474 			break;
475 		    case 'm':
476 		    case 'M':
477 		    default:
478 			genderlist[numplayers] = Gender_MALE;
479 			break;
480 		}
481 		*tmp = '\0';
482 	    }
483 	    numplayers++;
484 	}
485     }
486 
487     if (numplayers < 2) {
488 	printf("You have listed only %d players!\n", numplayers);
489 	exit(12);
490     }
491     if (numplayers > MAXPLAYERS) {
492 	printf("There is a maximum of %d players!\n", MAXPLAYERS);
493 	exit(12);
494     }
495 
496     gameval = BeginGame(numplayers, namelist, genderlist, &procs, &ignorerock);
497 
498     do {
499 	show_beings(gameval);
500 	val = 0;
501 	switch (TurnType(gameval)) {
502 	    case Turn_HASTE:
503 		printf("(hasted) ");
504 		break;
505 	    case Turn_TIMESTOP:
506 		printf("(timestopped) ");
507 		break;
508 	    case Turn_NORMAL:
509 	    default:
510 		break;
511 	}
512 	for (ix=0; ix<MAXPLAYERS; ix++)
513 	    if (TurnPlayerActive(gameval, ix)) {
514 		val++;
515 		printf("%d", ix);
516 	    }
517 	printf(": Enter moves: ");
518 	bzero(inbuf, numplayers*2);
519 	fgets(inbuf, 256, stdin);
520 	for (ix=0; ix<numplayers*2; ix++) {
521 	    movelist[ix] = cheap_translate(inbuf[ix]);
522 	}
523 	whowon = RunTurn(gameval, movelist);
524     } while (whowon < 0);
525 
526     if (whowon==MAXPLAYERS)
527 	printf("+++ the game is a draw +++\n");
528     else
529 	printf("+++ %s has won +++\n", namelist[whowon]);
530 
531     FreeGame(gameval);
532 }
533 
534