[BACK]Return to db_hangman.c CVS log [TXT][DIR] Up to [local] / sys / ddb

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