Annotation of sys/ddb/db_hangman.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: db_hangman.c,v 1.27 2006/07/07 12:42:13 mickey Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 1996 Theo de Raadt, Michael Shalayeff
! 5: * All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: *
! 16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 18: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 19: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 20: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 21: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 22: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 23: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 24: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 25: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 26: *
! 27: */
! 28:
! 29: #include <sys/param.h>
! 30:
! 31: #include <uvm/uvm_extern.h>
! 32:
! 33: #include <machine/db_machdep.h>
! 34:
! 35: #include <ddb/db_sym.h>
! 36: #include <ddb/db_extern.h>
! 37: #include <ddb/db_output.h>
! 38:
! 39: #include <dev/cons.h>
! 40: #include <dev/rndvar.h>
! 41:
! 42: #define ABC_ISCLR(c) sabc->abc[(c)-'a']==0
! 43: #define ABC_ISWRONG(c) sabc->abc[(c)-'a']=='_'
! 44: #define ABC_SETWRONG(c) (sabc->abc[(c)-'a']='_')
! 45: #define ABC_SETRIGHT(c) (sabc->abc[(c)-'a']='+')
! 46: #define ABC_CLR() memset(sabc->abc,0,sizeof sabc->abc)
! 47: struct _abc {
! 48: char abc[26+2]; /* for int32 alignment */
! 49: };
! 50:
! 51: #define TOLOWER(c) ((c)|0x20)
! 52: #define ISLOWALPHA(c) ('a'<=(c) && (c)<='z')
! 53: #define ISALPHA(c) ISLOWALPHA(TOLOWER(c))
! 54:
! 55: void db_hang(int, char *, struct _abc *);
! 56:
! 57: u_long db_plays, db_guesses;
! 58:
! 59: static const char hangpic[]=
! 60: "\n88888\r\n"
! 61: "9 7 6\r\n"
! 62: "97 5\r\n"
! 63: "9 423\r\n"
! 64: "9 2\r\n"
! 65: "9 1 0\r\n"
! 66: "9\r\n"
! 67: "9 ";
! 68: static const char substchar[]="\\/|\\/O|/-|";
! 69:
! 70: static size_t
! 71: db_random(size_t mod)
! 72: {
! 73: if (cold)
! 74: return (random() % mod);
! 75: return (arc4random() % mod);
! 76: }
! 77:
! 78: struct db_hang_forall_arg {
! 79: int cnt;
! 80: db_sym_t sym;
! 81: };
! 82:
! 83: /*
! 84: * Horrible abuse of the forall function, but we're not in a hurry.
! 85: */
! 86: static void db_hang_forall(db_symtab_t *, db_sym_t, char *, char *, int,
! 87: void *);
! 88:
! 89: static void
! 90: db_hang_forall(db_symtab_t *stab, db_sym_t sym, char *name, char *suff, int pre,
! 91: void *varg)
! 92: {
! 93: struct db_hang_forall_arg *arg = (struct db_hang_forall_arg *)varg;
! 94:
! 95: if (arg->cnt-- == 0)
! 96: arg->sym = sym;
! 97: }
! 98:
! 99: static __inline char *
! 100: db_randomsym(size_t *lenp)
! 101: {
! 102: extern db_symtab_t db_symtabs[];
! 103: db_symtab_t *stab;
! 104: int nsymtabs, nsyms;
! 105: char *p, *q;
! 106: struct db_hang_forall_arg dfa;
! 107:
! 108: for (nsymtabs = 0; db_symtabs[nsymtabs].name != NULL; nsymtabs++)
! 109: ;
! 110:
! 111: if (nsymtabs == 0)
! 112: return (NULL);
! 113:
! 114: stab = &db_symtabs[db_random(nsymtabs)];
! 115:
! 116: dfa.cnt = 0;
! 117: X_db_forall(stab, db_hang_forall, &dfa);
! 118: nsyms = -dfa.cnt;
! 119:
! 120: if (nsyms == 0)
! 121: return (NULL);
! 122:
! 123: dfa.cnt = db_random(nsyms);
! 124: X_db_forall(stab, db_hang_forall, &dfa);
! 125:
! 126: q = db_qualify(dfa.sym, stab->name);
! 127:
! 128: /* don't show symtab name if there are less than 3 of 'em */
! 129: if (nsymtabs < 3)
! 130: while (*q++ != ':');
! 131:
! 132: /* strlen(q) && ignoring underscores and colons */
! 133: for ((*lenp) = 0, p = q; *p; p++)
! 134: if (ISALPHA(*p))
! 135: (*lenp)++;
! 136:
! 137: return (q);
! 138: }
! 139:
! 140: void
! 141: db_hang(int tries, char *word, struct _abc *sabc)
! 142: {
! 143: const char *p;
! 144: int i;
! 145: int c;
! 146: #ifdef ABC_BITMASK
! 147: int m;
! 148: #endif
! 149:
! 150: for (p = hangpic; *p; p++)
! 151: cnputc((*p >= '0' && *p <= '9') ? ((tries <= (*p) - '0') ?
! 152: substchar[(*p) - '0'] : ' ') : *p);
! 153:
! 154: for (p = word; *p; p++) {
! 155: c = TOLOWER(*p);
! 156: cnputc(ISLOWALPHA(c) && ABC_ISCLR(c) ? '-' : *p);
! 157: }
! 158:
! 159: #ifdef ABC_WRONGSTR
! 160: db_printf(" (%s)\r", ABC_WRONGSTR);
! 161: #else
! 162: db_printf(" (");
! 163:
! 164: #ifdef ABC_BITMASK
! 165: m = sabc->wrong;
! 166: for (i = 'a'; i <= 'z'; ++i, m >>= 1)
! 167: if (m&1)
! 168: cnputc(i);
! 169: #else
! 170: for (i = 'a'; i <= 'z'; ++i)
! 171: if (ABC_ISWRONG(i))
! 172: cnputc(i);
! 173: #endif
! 174:
! 175: db_printf(")\r");
! 176: #endif
! 177: }
! 178:
! 179: void
! 180: db_hangman(db_expr_t addr, int haddr, db_expr_t count, char *modif)
! 181: {
! 182: char *word;
! 183: size_t tries;
! 184: size_t len;
! 185: struct _abc sabc[1];
! 186: int skill;
! 187:
! 188: if (modif[0] != 's' || (skill = modif[1] - '0') > 9U)
! 189: skill = 3;
! 190: word = NULL;
! 191: tries = 0;
! 192: for (;;) {
! 193:
! 194: if (word == NULL) {
! 195: ABC_CLR();
! 196:
! 197: tries = skill + 1;
! 198: word = db_randomsym(&len);
! 199: if (word == NULL)
! 200: break;
! 201:
! 202: db_plays++;
! 203: }
! 204:
! 205: {
! 206: int c;
! 207:
! 208: db_hang(tries, word, sabc);
! 209: c = cngetc();
! 210: c = TOLOWER(c);
! 211:
! 212: if (ISLOWALPHA(c) && ABC_ISCLR(c)) {
! 213: char *p;
! 214: size_t n;
! 215:
! 216: /* strchr(word,c) */
! 217: for (n = 0, p = word; *p ; p++)
! 218: if (TOLOWER(*p) == c)
! 219: n++;
! 220:
! 221: if (n) {
! 222: ABC_SETRIGHT(c);
! 223: len -= n;
! 224: } else {
! 225: ABC_SETWRONG(c);
! 226: tries--;
! 227: }
! 228: }
! 229: }
! 230:
! 231: if (tries && len)
! 232: continue;
! 233:
! 234: if (!tries && skill > 2) {
! 235: char *p = word;
! 236: for (; *p; p++)
! 237: if (ISALPHA(*p))
! 238: ABC_SETRIGHT(TOLOWER(*p));
! 239: }
! 240: if (tries)
! 241: db_guesses++;
! 242: db_hang(tries, word, sabc);
! 243: db_printf("\nScore: %lu/%lu\n", db_plays, db_guesses);
! 244: word = NULL;
! 245: if (tries)
! 246: break;
! 247: }
! 248: }
CVSweb