static void say_spell(struct char_data *ch, int spellnum, struct char_data *tch, struct obj_data *tobj) { char lbuf[256], buf[256], buf1[256], buf2[256]; /* FIXME */ const char *format; struct char_data *i; int j, ofs = 0; *buf = '\0'; strlcpy(lbuf, skill_name(spellnum), sizeof(lbuf)); while (lbuf[ofs]) { for (j = 0; *(syls[j].org); j++) { if (!strncmp(syls[j].org, lbuf + ofs, strlen(syls[j].org))) { strcat(buf, syls[j].news); /* strcat: BAD */ ofs += strlen(syls[j].org); break; } } /* i.e., we didn't find a match in syls[] */ if (!*syls[j].org) { log("No entry in syllable table for substring of '%s'", lbuf); ofs++; } } if (tch != NULL && IN_ROOM(tch) == IN_ROOM(ch)) { if (tch == ch) format = "$n closes $s eyes and utters the words, '%s'."; else format = "$n stares at $N and utters the words, '%s'."; } else if (tobj != NULL && ((IN_ROOM(tobj) == IN_ROOM(ch)) || (tobj->carried_by == ch))) format = "$n stares at $p and utters the words, '%s'."; else format = "$n utters the words, '%s'."; snprintf(buf1, sizeof(buf1), format, skill_name(spellnum)); snprintf(buf2, sizeof(buf2), format, buf); for (i = world[IN_ROOM(ch)].people; i; i = i->next_in_room) { if (i == ch || i == tch || !i->desc || !AWAKE(i)) continue; if (GET_CLASS(ch) == GET_CLASS(i)) perform_act(buf1, ch, tobj, tch, i); else perform_act(buf2, ch, tobj, tch, i); } if (tch != NULL && tch != ch && IN_ROOM(tch) == IN_ROOM(ch)) { snprintf(buf1, sizeof(buf1), "$n stares at you and utters the words, '%s'.", GET_CLASS(ch) == GET_CLASS(tch) ? skill_name(spellnum) : buf); act(buf1, FALSE, ch, NULL, tch, TO_VICT); } }
/* say_spell erodes buf, buf1, buf2 */ void say_spell(struct char_data *ch, struct spell_info_type *sptr, struct char_data *tch, struct obj_data *tobj) { char lbuf[256]; const char *format; struct char_data *i; int j, ofs = 0; *buf = '\0'; sprintf(lbuf, "%s", LOWERALL(sptr->name)); while (lbuf[ofs]) { for (j = 0; *(syls[j].org); j++) { if (!strncmp(syls[j].org, lbuf + ofs, strlen(syls[j].org))) { strcat(buf, syls[j].news); ofs += strlen(syls[j].org); break; } } /* i.e., we didn't find a match in syls[] */ if (!*syls[j].org) { extended_mudlog(NRM, SYSL_BUGS, TRUE, "No entry in syllable table for substring of '%s'", lbuf); ofs++; } } if (tch != NULL && IN_ROOM(tch) == IN_ROOM(ch)) { if (tch == ch) format = "$n closes $s eyes and utters the words, '&W%s&n'."; else format = "$n stares at $N and utters the words, '&W%s&n'."; } else if (tobj != NULL && ((IN_ROOM(tobj) == IN_ROOM(ch)) || (tobj->carried_by == ch))) format = "$n stares at $p and utters the words, '&W%s&n'."; else format = "$n utters the words, '&W%s&n'."; sprintf(buf1, format, sptr->name); sprintf(buf2, format, buf); for (i = world[IN_ROOM(ch)].people; i; i = i->next_in_room) { if (i == ch || i == tch || !i->desc || !AWAKE(i) || IN_OLC(i->desc) || PLR_FLAGGED(i, PLR_WRITING)) continue; if (GET_CLASS(ch) == GET_CLASS(i)) perform_act(buf1, ch, tobj, tch, i, 0); else perform_act(buf2, ch, tobj, tch, i, 0); } if (tch != NULL && tch != ch && IN_ROOM(tch) == IN_ROOM(ch)) { sprintf(buf1, "$n stares at you and utters the words, '&W%s&n'.", GET_CLASS(ch) == GET_CLASS(tch) ? sptr->name : buf); act(buf1, FALSE, ch, NULL, tch, TO_VICT); } }
/* * Return a string containing the AI's assumption about the best possible * move. */ void ai_assist(game *g, char *buf) { game sim; action current; char tmp[1024]; /* Clear best path */ best_path_pos = 0; best_path_score = -1; /* Simulate game */ simulate_game(&sim, g); /* Find best action path */ find_action(&sim); /* Check for no legal moves */ if (best_path_score == -1) { /* Add message */ strcpy(buf, "No legal moves!\n"); return; } /* Start back at beginning */ simulate_game(&sim, g); /* Clear buffer */ strcpy(buf, ""); /* Use buffer for assist messages */ assist_str = buf; /* Start at beginning of path */ best_path_pos = 0; /* Loop until done */ while (sim.p[g->turn].phase <= PHASE_ANNOUNCE) { /* Get current action */ current = best_path[best_path_pos]; /* Advance position */ best_path_pos++; /* Check current action */ switch (current.act) { /* None */ case ACT_NONE: /* No message */ strcpy(tmp, ""); break; /* Retreat */ case ACT_RETREAT: /* Add message */ sprintf(tmp, "Retreat\n"); break; /* Retrieve */ case ACT_RETRIEVE: /* Add message */ sprintf(tmp, "Retrieve %s\n", current.arg->name); break; /* Play */ case ACT_PLAY: /* Add message */ sprintf(tmp, "Play %s\n", current.arg->name); break; /* Play with no effect */ case ACT_PLAY_NO: /* Add message */ sprintf(tmp, "Play %s with no effect\n", current.arg->name); break; /* Announce fire */ case ACT_ANN_FIRE: /* Add message */ sprintf(tmp, "Announce fire\n"); break; /* Announce earth */ case ACT_ANN_EARTH: /* Add message */ sprintf(tmp, "Announce earth\n"); break; /* Use special */ case ACT_USE: /* Add message */ sprintf(tmp, "Use %s special text\n", current.arg->name); break; /* Satisfy */ case ACT_SATISFY: /* Add message */ sprintf(tmp, "Satisfy %s\n", current.arg->name); break; /* Land ship */ case ACT_LAND: /* Add message */ sprintf(tmp, "Land %s\n", current.arg->name); break; /* Load ship */ case ACT_LOAD: /* Add message */ sprintf(tmp, "Load %s onto %s\n", current.arg->name, current.target->name); break; /* Play bluff */ case ACT_BLUFF: /* Add message */ sprintf(tmp, "Bluff %s\n", current.arg->name); break; /* Reveal bluff */ case ACT_REVEAL: /* Add message */ sprintf(tmp, "Reveal %s\n", current.arg->name); break; } /* Add message to buffer */ strcat(buf, tmp); /* Perform action */ perform_act(&sim, current); /* Check for retreat */ if (current.act == ACT_RETREAT) break; /* Check for game over */ if (sim.game_over) break; } /* Clear assist string */ assist_str = NULL; }
/* * Have the AI player take an action. */ static void ai_take_action(game *g) { game sim; player *p; action current; int old_turn; /* Get player pointer */ p = &g->p[g->turn]; /* Save current turn */ old_turn = g->turn; /* Clear best path */ best_path_pos = 0; best_path_score = -1; /* Check for beginning of turn */ if (p->phase == PHASE_START) { /* Train networks with past inputs */ perform_training(g, g->turn, NULL); perform_training(g, !g->turn, NULL); } /* Clear random event flag */ g->random_event = 0; /* Check for error in handling choice nodes */ if (node_len > 0 || node_pos > 0) { printf("Choice nodes around\n"); } /* Simulate game */ simulate_game(&sim, g); #ifdef DEBUG printf("START\n"); #endif /* Find best action path */ find_action(&sim); #ifdef DEBUG printf("END\n"); #endif /* Start at beginning of path */ best_path_pos = 0; /* Loop until end */ while (1) { /* Get current action */ current = best_path[best_path_pos]; /* Check for error */ if (current.act == ACT_CHOOSE) { printf("Trying to perform choose action!\n"); break; } /* Advance to next */ best_path_pos++; /* Perform current action */ perform_act(g, current); /* Check for random event */ if (g->random_event) break; /* Check for retreat */ if (current.act == ACT_RETREAT) break; /* Check for turn change */ if (g->turn != old_turn) break; /* Check for game over */ if (g->game_over) break; } }
/* * Find the best "action path" available from the given state. * * We also return the score of the endstate that will result. * * We return -1 if no legal actions are available. * * This function is recursive. */ static double find_action(game *g) { game sim; player *p; int old_turn; int i, n; action legal[MAX_ACTION], best_act; double score, b_s = -1; /* Get player pointer */ p = &g->p[g->turn]; /* Get current player's turn */ old_turn = g->turn; /* Check for game over */ if (g->game_over) { /* Clear any choice nodes that haven't been examined */ node_len = node_pos; /* Return end of game score */ return eval_game(g, g->sim_turn); } /* Check for choice to make */ if (node_pos < node_len) { /* Handle choice node instead of normal */ return choose_action(g); } /* Avoid needlees work when checking for forced retreat */ if (checking_retreat && !must_retreat) return 0; /* Get legal actions to take */ n = legal_act(g, legal); /* Check for no legal actions */ if (!n) return -1; /* Check for only one possible action */ if (n == 1) { /* Increase path position for future searching */ best_path_pos++; #ifdef DEBUG /* Remember current path */ cur_path[best_path_pos] = legal[0]; #endif /* Perform that action */ perform_act(g, legal[0]); /* Check for turn change */ if (g->turn != old_turn) { /* Are we checking opponent's response */ if (checking_retreat) { /* Score is unimportant */ score = 0.0; /* We must not be forced to retreat */ must_retreat = 0; } else { /* Check for inevitable retreat from opponent */ check_retreat(g); /* Get score */ score = eval_game(g, g->sim_turn); /* Clear must retreat flag */ must_retreat = 0; } } /* Continue searching */ else score = find_action(g); /* Return to current path position */ best_path_pos--; /* Check for better actions than previously discovered */ if (!checking_retreat && score >= best_path_score) { /* Store action in best path */ best_path[best_path_pos] = legal[0]; /* Save best score seen */ best_path_score = score; } /* Return score */ return score; } /* Increase path position for future searching */ best_path_pos++; /* Loop over available actions */ for (i = 0; i < n; i++) { #ifdef DEBUG /* Remember current path */ cur_path[best_path_pos] = legal[i]; #endif /* Avoid unnecessary work when checking for forced retreat */ if (checking_retreat && !must_retreat) break; /* Copy game */ simulate_game(&sim, g); /* Perform action */ perform_act(&sim, legal[i]); /* Check for retreat */ if (legal[i].act == ACT_RETREAT && node_pos == node_len) { /* Are we checking for forced retreat */ if (checking_retreat) { /* Score is unimportant */ score = 0; } else { /* Get score */ score = eval_game(&sim, sim.sim_turn); } } /* Normal action */ else { /* Continue searching */ score = find_action(&sim); } /* Check for better score among actions */ if (score >= b_s) { /* Remember best */ b_s = score; best_act = legal[i]; } } /* Return to current path position */ best_path_pos--; /* Check for better actions than previously discovered */ if (!checking_retreat && b_s >= best_path_score) { /* Store action in best path */ best_path[best_path_pos] = best_act; /* Save best score seen */ best_path_score = b_s; } /* Return best score */ return b_s; }
/* say_spell erodes buf, buf1, buf2 */ void say_spell (struct char_data *ch, int spellnum, struct char_data *tch, struct obj_data *tobj) { char lbuf[256]; const char *format; struct char_data *i; int j, ofs = 0; *buf = '\0'; strcpy (lbuf, skill_name (spellnum)); while (lbuf[ofs]) { for (j = 0; *(syls[j].org); j++) { if (!strncmp (syls[j].org, lbuf + ofs, strlen (syls[j].org))) { strcat (buf, syls[j].news); ofs += strlen (syls[j].org); break; } } /* i.e., we didn't find a match in syls[] */ if (!*syls[j].org) { log ("No entry in syllable table for substring of '%s'", lbuf); ofs++; } } if (tch != NULL && IN_ROOM (tch) == IN_ROOM (ch)) { if (tch == ch) { if (IS_PSIONIC (ch) && (GET_LEVEL (ch) != LVL_IMPL)) { format = "$n congiunge le mani sulla testa e chiude i suoi occhi."; } else { format = "$n chiude i suoi occhi e lancia sul suo tricorder il processo, '%s'."; } } else { if (IS_PSIONIC (ch) && (GET_LEVEL (ch) != LVL_IMPL)) { format = "$n posa una mano sulla testa e punta l'altra su $N e chiude gli occhi."; } else { format = "$n punta il suo tricorder a $N e lancia il processo, '%s'."; } } } else if (tobj != NULL && ((IN_ROOM (tobj) == IN_ROOM (ch)) || (tobj->carried_by == ch))) { if (IS_PSIONIC (ch) && (GET_LEVEL (ch) != LVL_IMPL)) { format = "$n congiunge le mani su $p e chiude i suoi occhi."; } else { format = "$n punta il suo tricorder a $p e lancia il processo, '%s'."; } } else { if (IS_PSIONIC (ch) && (GET_LEVEL (ch) != LVL_IMPL)) { format = "$n congiunge le mani sulla testa e chiude i suoi occhi."; } else { format = "$n lancia sul suo tricorder il processo, '%s'."; } } sprintf (buf1, format, skill_name (spellnum)); sprintf (buf2, format, buf); for (i = world[IN_ROOM (ch)].people; i; i = i->next_in_room) { if (i == ch || i == tch || !i->desc || !AWAKE (i)) continue; if (GET_CLASS (ch) == GET_CLASS (i)) perform_act (buf1, ch, tobj, tch, i); else perform_act (buf2, ch, tobj, tch, i); } if (tch != NULL && tch != ch && IN_ROOM (tch) == IN_ROOM (ch)) { if (IS_PSIONIC (ch) && (GET_LEVEL (ch) != LVL_IMPL)) { sprintf (buf1, "$n posa una mano sulla testa e punta l'altra su di te."); } else { sprintf (buf1, "$n ti punta il suo tricorder e lancia il processo, '%s'.", GET_CLASS (ch) == GET_CLASS (tch) ? skill_name (spellnum) : buf); } act (buf1, FALSE, ch, NULL, tch, TO_VICT); } }