// // fmtb_parse_oldA.c - read a wpic*.txt file (stdin) and parse into motion codes (stdout) // // Copyright (C) 2006 Nathan (Acorn) Pooley // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // version 2 as published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License (gpl.txt) for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // You can contact the author, Nathan (Acorn) Pooley, by writing // to Nathan (Acorn) Pooley, 949 Buckeye Drive, Sunnyvale, CA 94086, USA // or through the form at http://www.rawbw.com/~acorn/wand/feedback.html // // // NOTE: BASED ON fmtb_parse.c rev 1.3 // //#@DOC@ read a wpic*.txt spell file (stdin) and parse into motion tokens // #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <ctype.h> #if 0 #include "tokens.h" #endif int OPT_quick = 0; int OPT_silent = 0; #define MAX_TOKENS 1000 #define TOKEN_CREATE(shape,dir,angle) \ ((((dir)<0 || (shape)==SSHP_PAUSE)?0x80:0) | \ (((angle)>>1) & 0xf) | \ (((shape)&7) << 4)) #define TOKEN_SHAPE(tok) (((tok)&0x70)>>4) #define TOKEN_DIR(tok) (((tok)&0x80)?-1:1) #define TOKEN_ANGLE(tok) (((tok)&0x0f)<<1) typedef enum SpellShapeEnum { SSHP_PAUSE, SSHP_CIRCLE, SSHP_OCIRCLE, SSHP_OPULSE, SSHP_PULSE, SSHP_WILD, SSHP_CNT } SpellShape; typedef struct SpellRec { int flags; int maxscore; int holdoff; char *name; char phonemes[30]; unsigned char tokens[MAX_TOKENS]; int len; int score; } Spell; typedef enum ShapeEnum { MSHP_PAUSE, MSHP_CLEAN_CIRCLE, MSHP_CLEAN_CIRCLE_PLUS, MSHP_DIRTY_CIRCLE, MSHP_DIRTY_CIRCLE_PLUS, MSHP_PULSE, MSHP_PULSE_PLUS, MSHP_CIRCLE_GAP, MSHP_CNT } Shape; static char *motionShapeStr[] = { "Pause ", "Cln Circ ", "Cln Circ+", "Drt Circ ", "Drt Circ+", "Pulse ", "Pulse+ ", "CircleGap", }; static char *quadStr[] = { "Down ", "Right", "Up ", "Left ", }; static char *octStr[] = { "d ", "dr", " r", "ur", "u ", "ul", " l", "dl", }; static char *octStr2[] = { "v", ".", ">", "'", "^", "`", "<", ",", }; extern Spell spells[]; int OPT_quiet = 1; int OPT_hex = 1; #define DEBUG 0 #define CNT_MAX 1024 #define ABS(a) ((a)<0?-(a):(a)) #define MIN(a,b) ((a)<(b)?(a):(b)) #define MAX(a,b) ((a)>(b)?(a):(b)) #define TH_T_STILL 0.25 #define TH_A_JUMP 5 #define TH_A_NEWQUAD 7 #define TH_A_SNAPQUAD 6 #define TH_A_CONNECT 2 typedef enum MotionFlagsEnum { MFLG_ZERO = 0x01, MFLG_MONO = 0x02, MFLG_CIRCLE = 0x04, MFLG_BEST_MAG = 0x08, MFLG_BEST_IMP = 0x10, MFLG_MISSING_CIRCLE = 0x20, MFLG_END = 0xff } MotionFlags; typedef struct MotionRec { int b_atime; int b_dtime; int b_imp; int b_minmag; int b_avgmag; int b_maxmag; int b_deltamag; int b_angle; int b_flags; struct MotionRec *c_next; struct MotionRec *c_prev; int c_shape; int c_time; int c_cnt; int c_imp; int c_isum; int c_dir; int c_maxstep; int c_oct; int c_best_angle; int c_best_mag; int c_flags; int c_maxdmag; int c_asum; #if 0 struct MotionRec *cc_next; int cc_shape; int cc_best_angle; int cc_imp; #endif int token; } Motion; #define PAUSE 0x80 Spell spells[] = { #include "spells.c" {0}, }; int ignoreSpells[8] = { 100, // SSHP_PAUSE 15, // SSHP_CIRCLE 0, // SSHP_OCIRCLE 1, // SSHP_OPULSE 100, // SSHP_PULSE 0, // SSHP_WILD 99999, 99999, }; int ignoreMotions[8] = { 0, // MSHP_PAUSE, 1, // MSHP_CLEAN_CIRCLE, 100, // MSHP_CLEAN_CIRCLE_PLUS, 1, // MSHP_DIRTY_CIRCLE, 20, // MSHP_DIRTY_CIRCLE_PLUS, 1, // MSHP_PULSE, 100, // MSHP_PULSE_PLUS, 0, // MSHP_CIRCLE_GAP, }; int scorePause[8] = { 0, // MSHP_PAUSE, 30, // MSHP_CLEAN_CIRCLE, 1000, // MSHP_CLEAN_CIRCLE_PLUS, 30, // MSHP_DIRTY_CIRCLE, 1000, // MSHP_DIRTY_CIRCLE_PLUS, 30, // MSHP_PULSE, 1000, // MSHP_PULSE_PLUS, 0, // MSHP_CIRCLE_GAP }; int scorePulse[10] = { 0, // same dir 0, // off by 1 0, // off by 2 0, // off by 3 0, // off by 4 (45 deg) 2, // off by 5 6, // off by 6 20, // off by 7 1000, // off by 8 (90 deg) 1000, // off by 9 }; //=========================================================================== // fatalError() //=========================================================================== void fatalError(const char *fmt, ...) { va_list ap; fprintf(stderr,"\n\nERROR:\n"); va_start(ap,fmt); vfprintf(stderr,fmt,ap); va_end(ap); fprintf(stderr,"\n\n"); exit(1); } //=========================================================================== // adiff() - returned signed difference of 2 angles //=========================================================================== int adiff(int a1, int a0) { int a = a1 - a0; a &= 0x1f; if (a & 0x10) a -= 0x20; return a; } //=========================================================================== // odiff() - returned signed difference of 2 octants //=========================================================================== int odiff(int o1, int o0) { int o = o1 - o0; o &= 0x7; if (o & 0x4) o -= 0x8; return o; } //=========================================================================== // a2quad() - convert angle to quadrant //=========================================================================== int a2quad(int a) { return ((a+4) >> 3) & 3; } //=========================================================================== // quad2a() - convert quadrant to angle //=========================================================================== int quad2a(int q) { return (q<<3) & 0x1f; } //=========================================================================== // a2oct() - convert angle to octant //=========================================================================== int a2oct(int a) { return ((a+2) >> 2) & 7; } //=========================================================================== // oct2a() - convert octant to angle //=========================================================================== int oct2a(int o) { return (o<<2) & 0x1f; } //=========================================================================== // spellTokenStr() //=========================================================================== char *spellTokenStr(int tok) { static char buf[10]; int oct = a2oct(TOKEN_ANGLE(tok)); int dir = TOKEN_DIR(tok); switch(TOKEN_SHAPE(tok)) { case SSHP_PAUSE: sprintf(buf,"Pause"); break; case SSHP_CIRCLE: sprintf(buf," %3s%s",dir<0?" CW":"CCW",octStr2[oct]); break; case SSHP_OCIRCLE: sprintf(buf," %3s%s",dir<0?" cw":"ccw",octStr2[oct]); break; case SSHP_OPULSE: sprintf(buf," op%s",octStr2[oct]); break; case SSHP_PULSE: sprintf(buf," P%s",octStr2[oct]); break; case SSHP_WILD: sprintf(buf,"Wild "); break; default: sprintf(buf,"?????"); break; } return buf; } //=========================================================================== // motionTokenStr() //=========================================================================== char *motionTokenStr(unsigned int tok) { static char buf[10]; int oct = a2oct(TOKEN_ANGLE(tok)); int dir = TOKEN_DIR(tok); switch(TOKEN_SHAPE(tok)) { case MSHP_PAUSE: sprintf(buf,"PAUSE"); break; case MSHP_CLEAN_CIRCLE: sprintf(buf," %3s%s",dir<0?" CW":"CCW",octStr2[oct]); break; case MSHP_CLEAN_CIRCLE_PLUS: sprintf(buf,"+%3s%s",dir<0?" CW":"CCW",octStr2[oct]); break; case MSHP_DIRTY_CIRCLE: sprintf(buf," %3s%s",dir<0?" cw":"ccw",octStr2[oct]); break; case MSHP_DIRTY_CIRCLE_PLUS: sprintf(buf,"+%3s%s",dir<0?" cw":"ccw",octStr2[oct]); break; case MSHP_PULSE: sprintf(buf," p%s",octStr2[oct]); break; case MSHP_PULSE_PLUS: sprintf(buf," +P%s",octStr2[oct]); break; case MSHP_CIRCLE_GAP: sprintf(buf,"G%3s%s",dir<0?" cw":"ccw",octStr2[oct]); break; default: sprintf(buf,"?????"); break; } return buf; } //=========================================================================== // flagStr() //=========================================================================== const char *flagStr(int f) { static char s[10]; s[0] = f & MFLG_ZERO ? 'Z' : ' '; s[1] = f & MFLG_MONO ? 'M' : ' '; s[2] = f & MFLG_CIRCLE ? 'C' : ' '; s[3] = f & MFLG_BEST_MAG ? 'G' : ' '; s[4] = f & MFLG_BEST_IMP ? 'I' : ' '; s[5] = 0; return s; } //=========================================================================== // lookPrint() //=========================================================================== void lookPrint(Motion *mlist, int mcnt) { Motion *m, *mp; if (OPT_silent) return; mp = 0; #if 0 for (m=mlist; m; mp=m, m = m->c_next) { if (m->b_angle == 0xff) { printf(" 0x%08x: %04x Pause\n", m->b_atime, m->c_time); } else { printf(" 0x%08x: %04x shape=%d %s a=%02x %c %d%s %s d=%2d imp=%04x %04x MaxDMag=%02x maxStep=%02x " "ad=%3d flg=%02x %s %02x %s\n", m->b_atime, m->c_time, m->c_shape, motionShapeStr[m->c_shape], m->c_best_angle, quadStr[a2quad(m->c_best_angle)][0], m->c_oct, octStr[m->c_oct], octStr2[m->c_oct], m->c_dir, m->c_imp, m->c_isum, m->c_maxdmag, m->c_maxstep, (m==mlist || m->b_angle == 0xff || mp->b_angle == 0xff) ? 0:adiff(m->c_best_angle,mp->c_best_angle), m->c_flags, flagStr(m->c_flags), m->token, motionTokenStr(m->token)); } } #else for (m=mlist; m; mp=m, m = m->c_next) { if (m->b_angle == 0xff) { printf("AA2 0x%08x: %04x Pause\n", m->b_atime, m->c_time); } else { printf("AA2 0x%08x: %04x shape=%d %s a=%02x %c %d%s %s d=%2d imp=%04x %04x MaxDMag=%02x maxStep=%02x " "ad=%3d flg=%02x %s %02x %s\n", m->b_atime, m->b_dtime, 0, //m->c_shape, motionShapeStr[m->c_shape], m->c_best_angle, quadStr[a2quad(m->c_best_angle)][0], m->c_oct, octStr[m->c_oct], octStr2[m->c_oct], m->c_dir, m->c_imp, 0, //m->c_isum, m->b_deltamag, //m->c_maxdmag, 0, //m->c_maxstep, (m==mlist || m->b_angle == 0xff || mp->b_angle == 0xff) ? 0:adiff(m->c_best_angle,mp->c_best_angle), m->c_flags, flagStr(m->c_flags), 0, //m->token, motionTokenStr(m->token)); } } #endif printf("\n\n"); } //=========================================================================== // initialPrint() - print initial motion data //=========================================================================== static void initialPrint(Motion *mlist) { Motion *m; if (OPT_silent) return; #if 0 for (m=mlist; m->b_angle != 0xfe; m++) { if (m->b_angle == 0xff) { printf("AA1 0x%08x: %04x Pause\n", m->b_atime, m->b_dtime); } else { printf("AA1 0x%08x: %04x a=%02x %c %c imp=%04x mag=%02x %02x %02x dmag=%02x %02x (%5.3f)" " flg=%02x %s\n", m->b_atime, m->b_dtime, m->b_angle, quadStr[a2quad(m->b_angle)][0], octStr2[a2oct(m->b_angle)][0], m->b_imp, m->b_minmag, 0, //m->b_avgmag, m->b_maxmag, m->b_maxmag-m->b_minmag, m->b_deltamag, (double)m->b_deltamag/(double)m->b_maxmag, m->b_flags, flagStr(m->b_flags)); } } #else for (m=mlist; m->b_angle != 0xfe; m++) { if (m->b_angle == 0xff) { printf("AA1 0x%08x: %04x Pause\n", m->b_atime, m->b_dtime); } else { printf("AA1 0x%08x: %04x a=%02x %c %c imp=%04x mag=%02x %02x %02x dmag=%02x %02x (%5.3f)" " flg=%02x %s\n", m->b_atime, m->b_dtime, m->b_angle, quadStr[a2quad(m->b_angle)][0], octStr2[a2oct(m->b_angle)][0], m->b_imp, m->b_minmag, 0, //m->b_avgmag, m->b_maxmag, m->b_maxmag-m->b_minmag, m->b_deltamag, (double)m->b_deltamag/(double)m->b_maxmag, m->b_flags, flagStr(m->b_flags)); } } #endif printf("\n\n"); } //=========================================================================== // parse1() //=========================================================================== void parse1(Motion *mlist, int mcnt) { Motion *m; Motion *ms = 0; int maxstep = 0; for (m=mlist; m->b_angle != 0xfe; m++) { int o = a2oct(m->b_angle); int restart = 0; int ad = 0; int step = 0; int dir = 0; if (m->b_angle == 0xfe) { m = 0; } if (!m || !ms) { restart = 1; } else if (m->b_angle == 0xff) { restart = ms->b_angle != 0xff; } else if (ms->b_angle == 0xff) { restart = 1; } else { restart = o != a2oct(ms->b_angle); ad = adiff(m->b_angle, (m-1)->b_angle); step = ABS(ad); dir = ad < 0 ? -1 : 1; } if (step > maxstep) { maxstep = step; } if (restart) { if (ms) { ms->c_asum += step; if (dir != ms->c_dir) { ms->c_flags &= ~MFLG_MONO; } if ((ms->c_flags & MFLG_MONO) == 0) { ms->c_asum = 0; ms->c_dir = 0; } if (ms->b_angle == 0xff) { ms->c_shape = MSHP_PAUSE; } else if (ms == mlist || !m || (ms-1)->b_angle == 0xff || m->b_angle==0xff) { ms->c_shape = MSHP_PULSE; } else if ((ms->c_flags&MFLG_MONO) && maxstep<=5 && ms->c_asum >= 4) { ms->c_shape = MSHP_DIRTY_CIRCLE; if (maxstep<=3 && ms->c_maxdmag<8 && (ms->c_flags & MFLG_ZERO)==0) { ms->c_shape = MSHP_CLEAN_CIRCLE; } } else { ms->c_shape = MSHP_PULSE; } ms->c_next = m; m->c_prev = ms; } if (!m) break; ms = m; ms->c_dir = dir; ms->c_cnt = 1; ms->c_imp = ms->b_imp; ms->c_time = ms->b_dtime; ms->c_maxstep = maxstep; ms->c_oct = o; ms->c_best_angle = ms->b_angle; ms->c_best_mag = ms->b_maxmag; ms->c_flags = ms->b_flags | MFLG_MONO; ms->c_maxdmag = ms->b_deltamag; ms->c_asum = step; maxstep = step; ms->c_next = 0; } else { ms->c_cnt++; ms->c_time += m->b_dtime; if (m->b_angle == 0xff) { // double pause - ignore } else { if (dir != ms->c_dir) { ms->c_flags &= ~MFLG_MONO; } ms->c_imp += m->b_imp; if (m->b_maxmag > ms->c_best_mag) { ms->c_best_angle = m->b_angle; ms->c_best_mag = m->b_maxmag; } ms->c_flags |= m->b_flags; ms->c_maxdmag = MAX(ms->c_maxdmag, m->b_deltamag); ms->c_asum += step; } } } } #if 0 //=========================================================================== // findCircles() //=========================================================================== void findCircles(Motion *mlist, int mcnt) { Motion *ms, *m, *mp; int asum; int got_pulse = 0; for (ms=mlist; ms; mp2=ms, ms=ms->c_next) { ms->cc_shape = ms->c_shape; if (ms->c_shape == MSHP_PAUSE) continue; if (ms->c_shape == MSHP_PULSE) continue; asum = ms->c_asum; got_pulse = 0; for (mp=ms, m=ms->c_next; m; mp=m, m=m->c_next) { m->cc_shape = m->c_shape; if (got_pulse) break; if (m->c_shape == MSHP_PAUSE) break; if (mp->dir && m->dir && mp->dir!=m->dir) break; if (m->c_shape == MSHP_PULSE) got_pulse = 1; if ( } } } //=========================================================================== // combinePulses() //=========================================================================== void combinePulses(Motion *mlist, int mcnt) { Motion *m, *ms, *mp, *mp2; int best_imp = 0; int ad; mp2 = 0; for (ms=mlist; ms; mp2=ms, ms = ms->cc_next) { ms->cc_imp = ms->c_imp; ms->cc_next = ms->c_next; ms->cc_best_angle = ms->c_best_angle; ms->cc_shape = ms->c_shape; if (ms->cc_shape == MSHP_DIRTY_CIRCLE && mp2 && mp2->cc_shape == MSHP_CLEAN_CIRCLE) continue; if (ms->cc_shape != MSHP_PULSE && ms->cc_shape != MSHP_DIRTY_CIRCLE) continue; best_imp = ms->c_imp; for (mp=ms, m=ms->c_next; m; mp=m, m=m->c_next) { if (m->c_shape != MSHP_PULSE && m->c_shape != MSHP_DIRTY_CIRCLE) break; if (m->c_shape == MSHP_DIRTY_CIRCLE) { Motion *m2; for (m2=m->c_next; m2; m2=m2->c_next) { if (m2->c_shape != MSHP_DIRTY_CIRCLE) break; } if (m2 && m2->c_shape == MSHP_CLEAN_CIRCLE) break; } ad = adiff(m->c_best_angle,mp->c_best_angle); if (ABS(ad) > 5) break; if (m->c_imp > best_imp) { best_imp = m->c_imp; ms->cc_best_angle = m->c_best_angle; } ms->cc_imp += m->c_imp; ms->cc_next = m->c_next; } } } #endif #if 0 //=========================================================================== // findStrongPulses() //=========================================================================== void findStrongPulses(Motion *mlist, int mcnt) { Motion *ms, *mp=0, *m_best_mag=0, *m_best_imp=0; for (ms=mlist; ms; mp2=ms, ms=ms->c_next) { int restart = 0; if (ms->c_shape == MSHP_PAUSE) { restart = 1; mp = 0; } else if (!mp) { restart = 1; mp = ms; } else { int doct = a2oct(ms->c_best_angle) - a2oct(mp->c_best_angle); doct &= 7; if (doct & 4) doct -= 8; if (ABS(doct) > 1) { restart = 1; } else { if (ms->c_imp > } mp = ms; } if (restart) { if (m_best_mag) { m_best_mag->c_flags |= MFLG_BEST_MAG; } if (m_best_imp) { m_best_imp->c_flags |= MFLG_BEST_IMP; } m_best_mag = mp; m_best_imp = mp; } ms->cc_imp = ms->c_imp; ms->cc_next = ms->c_next; ms->cc_best_angle = ms->c_best_angle; ms->c_shape = ms->c_shape; if (ms->c_shape == MSHP_DIRTY_CIRCLE && mp2 && mp2->c_shape == MSHP_CLEAN_CIRCLE) continue; if (ms->c_shape != MSHP_PULSE && ms->c_shape != MSHP_DIRTY_CIRCLE) continue; best_imp = ms->c_imp; for (mp=ms, m=ms->c_next; m; mp=m, m=m->c_next) { if (m->c_shape != MSHP_PULSE && m->c_shape != MSHP_DIRTY_CIRCLE) break; if (m->c_shape == MSHP_DIRTY_CIRCLE) { Motion *m2; for (m2=m->c_next; m2; m2=m2->c_next) { if (m2->c_shape != MSHP_DIRTY_CIRCLE) break; } if (m2 && m2->c_shape == MSHP_CLEAN_CIRCLE) break; } ad = adiff(m->c_best_angle,mp->c_best_angle); if (ABS(ad) > 5) break; if (m->c_imp > best_imp) { best_imp = m->c_imp; ms->cc_best_angle = m->c_best_angle; } ms->cc_imp += m->c_imp; ms->cc_next = m->c_next; } } } #endif //=========================================================================== // insertNode() //=========================================================================== Motion *insertNode(Motion *mlist, Motion *prev) { // NOTE: MEMORY LEAK! these are never freed Motion *m = malloc(sizeof(Motion)); memcpy(m,prev,sizeof(*m)); m->c_prev = prev; m->c_next = prev->c_next; prev->c_next = m; if (prev->c_next) prev->c_next->c_prev = m; m->b_atime = m->c_next->b_atime; m->b_dtime = 0; m->b_imp = 0; m->b_minmag = 0; m->b_avgmag = 0; m->b_maxmag = 0; m->b_deltamag = 0; //m->b_angle; //m->b_flags; //m->c_shape; m->c_time = 0; m->c_cnt = 0; m->c_imp = 0; m->c_isum = 0; //m->c_dir; m->c_maxstep = 0; //m->c_best_angle; //m->c_best_mag; //m->c_flags; //m->c_maxdmag; //m->c_asum; //m->token; return m; } //=========================================================================== // fillCircleGaps() //=========================================================================== int fillCircleGaps(Motion *mlist, int mcnt) { Motion *ms, *m, *mg; int cnt0, cnt1; int oct0, oct; int added = 0; printf("start fillCircleGaps\n"); // // check counter-clockwise circles (dir == 1) // for (ms=mlist; ms; ) { if (ms->c_dir < 0) { ms = ms->c_next; continue; } cnt0 = 1; oct0 = ms->c_oct; for (m=ms->c_next; m; m=m->c_next) { if (m->c_dir < 0) { break; } oct = m->c_oct; if (((oct - oct0)&7) != 1) break; cnt0++; oct0 = oct; } if (!m) break; if (m->c_dir < 0 || ((oct - oct0)&7) != 2) { ms = m; continue; } mg = m; cnt1 = 1; oct0 = oct; for (m=m->c_next; m; m=m->c_next) { oct = m->c_oct; if (((oct - oct0)&7) != 1) break; cnt1++; oct0 = oct; } if (cnt0>=2 && cnt1>=2 && (cnt0+cnt1 > 5)) { m = insertNode(mlist,mg->c_prev); m->c_dir = 1; m->c_maxstep = 0; m->c_oct = (mg->c_oct - 1) & 7; m->c_best_angle = oct2a(m->c_oct); m->b_angle = m->c_best_angle; m->c_flags = MFLG_MONO | MFLG_MISSING_CIRCLE; m->c_shape = MSHP_CIRCLE_GAP; added++; } ms = ms->c_next; } // // check counter-clockwise circles (dir == -1) // for (ms=mlist; ms; ) { if (ms->c_dir > 0) { ms = ms->c_next; continue; } cnt0 = 1; oct0 = ms->c_oct; for (m=ms->c_next; m; m=m->c_next) { if (m->c_dir > 0) { break; } oct = m->c_oct; if (((oct - oct0)&7) != 7) break; cnt0++; oct0 = oct; } if (!m) break; if (m->c_dir > 0 || ((oct - oct0)&7) != 6) { ms = m; continue; } mg = m; cnt1 = 1; oct0 = oct; for (m=m->c_next; m; m=m->c_next) { oct = m->c_oct; if (((oct - oct0)&7) != 7) break; cnt1++; oct0 = oct; } if (cnt0>=2 && cnt1>=2 && (cnt0+cnt1 > 5)) { m = insertNode(mlist,mg->c_prev); m->c_dir = -1; m->c_maxstep = 0; m->c_oct = (mg->c_oct + 1) & 7; m->c_best_angle = oct2a(m->c_oct); m->b_angle = m->c_best_angle; m->c_flags = MFLG_MONO | MFLG_MISSING_CIRCLE; m->c_shape = MSHP_CIRCLE_GAP; added++; } ms = ms->c_next; } printf("end fillCircleGaps (added %d)\n",added); return added; } //=========================================================================== // findWeakCircles() //=========================================================================== void findWeakCircles(Motion *mlist, int mcnt) { Motion *ms, *m, *m2; int dcnt, ccnt; printf("start findWeakCircles\n"); for (ms=mlist; ms; ) { ccnt = dcnt = 0; for (m=ms; m; m=m->c_next) { if (m->c_shape == MSHP_DIRTY_CIRCLE) { dcnt++; } else if (m->c_shape == MSHP_CLEAN_CIRCLE) { ccnt++; } else { break; } } if (ccnt > 4 || (ccnt>0 && ccnt+dcnt>5)) { for (m2=ms; m2!=m; m2=m2->c_next) { m2->c_flags |= MFLG_CIRCLE; } m2 = ms->c_prev; if (m2->c_shape == MSHP_PULSE && (m2->c_flags & MFLG_MONO) && m2->c_dir == ms->c_dir) { int d = odiff(m2->c_oct, ms->c_oct); if (ABS(d) < 2) { m2->c_flags |= MFLG_CIRCLE; } } m2 = m->c_prev; if (m->c_shape == MSHP_PULSE && (m->c_flags & MFLG_MONO) && m->c_dir == ms->c_dir) { int d = odiff(m->c_oct, m2->c_oct); if (ABS(d) < 2) { m->c_flags |= MFLG_CIRCLE; } } } else if (ccnt>0) { for (m2=ms; m2!=m; m2=m2->c_next) { m2->c_shape = MSHP_DIRTY_CIRCLE; } } ms = m==ms ? m->c_next : m; } printf("end findWeakCircles\n"); } //=========================================================================== // findBestPulses() //=========================================================================== void findBestPulses(Motion *mlist, int mcnt) { Motion *m, *ms; Motion *best_imp=0, *best_mag=0; int d; int isum = 0; printf("start findBestPulses\n"); for (ms=mlist; ms; ms = ms->c_next) { ms->c_isum = ms->c_imp; if (ms->c_shape == MSHP_DIRTY_CIRCLE && ms->c_prev->c_shape == MSHP_CLEAN_CIRCLE) continue; if (ms->c_shape != MSHP_PULSE && ms->c_shape != MSHP_DIRTY_CIRCLE) continue; best_imp = ms; best_mag = ms; isum = ms->c_imp; for (m=ms->c_next; m; m=m->c_next) { m->c_isum = m->c_imp; if (m->c_shape != MSHP_PULSE && m->c_shape != MSHP_DIRTY_CIRCLE) break; if (m->c_shape == MSHP_DIRTY_CIRCLE && (m->c_flags & MFLG_CIRCLE)) break; d = adiff(m->c_best_angle,m->c_prev->c_best_angle); if (ABS(d) > 5) break; d = odiff(m->c_oct, m->c_prev->c_oct); if (ABS(d) > 1) break; if (m->c_best_mag > best_mag->c_best_mag) { best_mag = m; } if (m->c_imp > best_imp->c_imp) { best_imp = m; } isum += m->c_imp; } best_imp->c_isum = isum; if (isum > 0x500) { best_imp->c_flags |= MFLG_BEST_IMP; best_mag->c_flags |= MFLG_BEST_MAG; if (best_imp == best_mag) { switch(best_imp->c_shape) { case MSHP_PULSE: best_imp->c_shape = MSHP_PULSE_PLUS; break; case MSHP_DIRTY_CIRCLE: best_imp->c_shape = MSHP_DIRTY_CIRCLE_PLUS; break; case MSHP_CLEAN_CIRCLE: best_imp->c_shape = MSHP_CLEAN_CIRCLE_PLUS; break; } } } ms = m->c_prev; } printf("end findBestPulses\n"); } //=========================================================================== // markLast() - mark last few(3) pulses as unimportant //=========================================================================== void markLast(Motion *mlist, int mcnt) { Motion *m; int cnt = 0; if (!mlist) return; for (m=mlist; m->c_next; m=m->c_next); while(m && cnt<3) { switch(m->c_shape) { case MSHP_PAUSE: break; case MSHP_CLEAN_CIRCLE: case MSHP_DIRTY_CIRCLE: case MSHP_PULSE: case MSHP_CIRCLE_GAP: cnt++; break; case MSHP_CLEAN_CIRCLE_PLUS: m->c_shape = MSHP_CLEAN_CIRCLE; cnt++; break; case MSHP_DIRTY_CIRCLE_PLUS: m->c_shape = MSHP_DIRTY_CIRCLE; cnt++; break; case MSHP_PULSE_PLUS: m->c_shape = MSHP_PULSE; cnt++; break; } m = m->c_prev; } } #if 0 //=========================================================================== // removeWeakPulses() //=========================================================================== void removeWeakPulses(Motion *mlist, int mcnt) { Motion *m, *ms, *mp, *mp2; int d; int isum = 0; printf("start removeWeakPulses\n"); mp = 0; for (ms=mlist; ms; mp=ms, ms = ms->c_next) { if ( ms->c_isum = ms->c_imp; if (ms->c_shape == MSHP_DIRTY_CIRCLE && mp2 && mp2->c_shape == MSHP_CLEAN_CIRCLE) continue; if (ms->c_shape != MSHP_PULSE && ms->c_shape != MSHP_DIRTY_CIRCLE) continue; best_imp = ms; best_mag = ms; isum = ms->c_imp; for (mp=ms, m=ms->c_next; m; mp=m, m=m->c_next) { m->c_isum = m->c_imp; if (m->c_shape != MSHP_PULSE && m->c_shape != MSHP_DIRTY_CIRCLE) break; if (m->c_shape == MSHP_DIRTY_CIRCLE && (m->c_flags & MFLG_CIRCLE)) break; d = adiff(m->c_best_angle,mp->c_best_angle); if (ABS(d) > 5) break; d = adiff(a2oct(m->c_best_angle)<<2, a2oct(mp->c_best_angle)<<2); if (ABS(d) > 4) break; if (m->c_best_mag > best_mag->c_best_mag) { best_mag = m; } if (m->c_imp > best_imp->c_imp) { best_imp = m; } isum += m->c_imp; } best_imp->c_isum = isum; best_imp->c_flags |= MFLG_BEST_IMP; best_mag->c_flags |= MFLG_BEST_MAG; ms = mp; } printf("end removeWeakPulses\n"); } #endif //=========================================================================== // tokenize() //=========================================================================== void tokenize(Motion *mlist, int mcnt) { Motion *m; for (m=mlist; m; m=m->c_next) { int a = m->c_best_angle; if (m->c_shape != MSHP_PULSE_PLUS) { while(1) { int d = odiff(m->c_oct, a2oct(a)); if (!d) break; a = (a + (d<0?-1:1)) & 0x1f; } } m->token = TOKEN_CREATE(m->c_shape, m->c_dir, a); } } //=========================================================================== // look() //=========================================================================== void look(Motion *mlist, int mcnt) { #if 1 printf("\n\n"); parse1(mlist,mcnt); if (!OPT_silent) { printf("\nPOST parse1\n\n"); lookPrint(mlist,mcnt); } while(fillCircleGaps(mlist,mcnt)); if (!OPT_silent) { printf("\nPOST fillCircleGaps\n\n"); lookPrint(mlist,mcnt); } findWeakCircles(mlist,mcnt); if (!OPT_silent) { printf("\nPOST findWeakCircles\n\n"); lookPrint(mlist,mcnt); } findBestPulses(mlist,mcnt); if (!OPT_silent) { printf("\nPOST findBestPulses\n\n"); lookPrint(mlist,mcnt); } markLast(mlist,mcnt); if (!OPT_silent) { printf("\nPOST markLast\n\n"); lookPrint(mlist,mcnt); } tokenize(mlist,mcnt); if (!OPT_silent) { printf("\nPOST tokenize\n\n"); lookPrint(mlist,mcnt); } #else printf("\n\n"); parse1(mlist,mcnt); lookPrint(mlist,mcnt); while(fillCircleGaps(mlist,mcnt)); lookPrint(mlist,mcnt); findWeakCircles(mlist,mcnt); lookPrint(mlist,mcnt); findBestPulses(mlist,mcnt); markLast(mlist,mcnt); tokenize(mlist,mcnt); lookPrint(mlist,mcnt); #endif } //=========================================================================== // getline2() //=========================================================================== int getline2(FILE *fp, char *line, char *end) { int c = getc(fp); if (c==EOF) return 0; end--; while(c!='\n' && c!=EOF && line != end) { *(line++) = c; c = getc(fp); } *line = 0; return 1; } //=========================================================================== // getline() //=========================================================================== int getline(FILE *fp, Motion *m) { float list[6]; int idx = 0; char line[1000]; char *s, *e; while(1) { if (!getline2(fp,line,line+sizeof(line))) { return 0; } s = line; while(1) { while(isspace(*s)) s++; if (*s == '#' || *s == 0) { break; } list[idx] = strtod(s,&e); if (!e || e==s) { fprintf(stderr,"Error parsing line:\n %s\n",line); break; } s = e; idx++; if (idx >= sizeof(list)/sizeof(list[0])) break; } if (idx) { while (idx < sizeof(list)/sizeof(list[0])) { list[idx++] = 0.0; } m->b_dtime = list[0]; m->b_angle = list[1]; m->b_imp = list[2]; m->b_minmag = list[3]; m->b_maxmag = list[4]; m->b_flags = list[5]; m->b_avgmag = (m->b_minmag + m->b_maxmag)/2; m->b_deltamag = m->b_maxmag - m->b_minmag; if (m->b_flags & MFLG_ZERO) { m->b_deltamag = m->b_maxmag; } if (m->b_dtime > 0) { m->b_avgmag = m->b_imp / m->b_dtime; } if (m->b_angle == 0xff) { m->b_imp = 0; m->b_minmag = 0; m->b_maxmag = 0; m->b_flags = 0; m->b_avgmag = 0; m->b_deltamag = 0; } return 1; } } } //=========================================================================== // get() - read the file //=========================================================================== int get(FILE *in, Motion *m, Motion *end) { int atime = 0; int cnt = 0; // // start with a pause // m->b_atime = 0; m->b_angle = 0xff; m++; cnt++; while(m != end-1 && getline(in,m)) { m->b_atime = atime; atime += m->b_dtime; m++; cnt++; } // // end with a pause // m->b_atime = 0; m->b_angle = 0xff; m++; cnt++; m->b_angle = 0xfe; return cnt; } //=========================================================================== // compareToken() //=========================================================================== void compareToken(int *ignoreMotion, int *ignoreSpell, int *val, int stok, int mtok) { int mshape = TOKEN_SHAPE(mtok); int mdir = TOKEN_DIR(mtok); int mangle = TOKEN_ANGLE(mtok); int sshape = TOKEN_SHAPE(stok); int sdir = TOKEN_DIR(stok); int sangle = TOKEN_ANGLE(stok); int d; int add = 0; *ignoreMotion = ignoreMotions[mshape]; *ignoreSpell = ignoreSpells[sshape]; *val = 10000; switch(sshape) { case SSHP_PAUSE: *val = scorePause[mshape]; case SSHP_CIRCLE: case SSHP_OCIRCLE: switch(mshape) { case MSHP_CLEAN_CIRCLE_PLUS: case MSHP_DIRTY_CIRCLE_PLUS: case MSHP_CLEAN_CIRCLE: case MSHP_DIRTY_CIRCLE: case MSHP_CIRCLE_GAP: if (mdir != sdir) break; d = a2oct(mangle) - a2oct(sangle); if (d) break; *val = 0; break; case MSHP_PULSE: case MSHP_PULSE_PLUS: d = a2oct(mangle) - a2oct(sangle); if (d) break; *val = 0; break; case MSHP_PAUSE: break; } break; case SSHP_PULSE: case SSHP_OPULSE: switch(mshape) { case MSHP_CLEAN_CIRCLE: //add += 4; case MSHP_DIRTY_CIRCLE: //add += 2; case MSHP_PULSE: //add += 2; case MSHP_CLEAN_CIRCLE_PLUS: case MSHP_DIRTY_CIRCLE_PLUS: case MSHP_PULSE_PLUS: d = adiff(mangle, sangle); d = ABS(d); if (d < 10) { *val = scorePulse[d] + add; } break; case MSHP_PAUSE: case MSHP_CIRCLE_GAP: break; } break; case SSHP_WILD: *val = 1; break; default: fatalError("Bad token in compareToken\n"); } } //=========================================================================== // printColor() //=========================================================================== void printColor(int diff) { if (diff<0) diff = -diff; printf("%c[%sm",0x1b, (diff)>=10 ? "37;41" : (diff)>=4 ? "30;43" : (diff)>=1 ? "37;44" : "37;42"); } //=========================================================================== // scoreSpell() //=========================================================================== int scoreSpell(Spell *spell, Motion *mlist, char *path, int doprint) { Motion *m; unsigned char *spellTokens; unsigned char *s; static int mtx[1000]; int scnt,mcnt,slen; int ignoreMotion, ignoreSpell, match, val, corner, lastval = 0; // // get rid of leading pause // for (s=spell->tokens; *s && TOKEN_SHAPE(*s) == SSHP_PAUSE; s++); spellTokens = s; if (doprint==2) { printf(" "); for (scnt=1, s=spellTokens; *s; scnt++, s++) { printf("%5s ",spellTokenStr(*s)); } printf("\n "); for (scnt=1, s=spellTokens; *s; scnt++, s++) { printf(" 0x%02x ",*s); } printf("\n %-4d ",0); } else if (doprint==3) { printf(" %5s\n",spell->name); printf(" %5s %5s\n","spell","motion"); } mtx[0] = 0; for (scnt=1, s=spellTokens; *s; scnt++, s++) { compareToken(&ignoreMotion, &ignoreSpell, &match, *s, MSHP_PAUSE<<4); mtx[scnt] = val = mtx[scnt-1] + ignoreSpell; if (doprint==2) { if (path[scnt]) { printColor(val-lastval); lastval = val; } printf("<%-4d",mtx[scnt]); printf("%c[0m ",0x1b); } else if (doprint==3 && path[scnt]) { printf(" %5s %d %5s ", spellTokenStr(*s), a2oct(a2oct(TOKEN_ANGLE(*s))), "skip"); printColor(ignoreSpell); printf("%4d %4d%c[0m\n",ignoreSpell,val,0x1b); } else if (doprint == -1) { path[scnt] = '<'; } } slen = scnt; for (mcnt=1, m = mlist; m; mcnt++, m=m->c_next) { corner = mtx[0]; compareToken(&ignoreMotion, &ignoreSpell, &match, PAUSE, m->token); mtx[0] = val = corner + ignoreMotion; if (doprint==2) { printf("\n%5s %02x ",motionTokenStr(m->token),0/*m->token*/); if (path[slen*mcnt]) { printColor(match-lastval); lastval = val; } printf("^%-4d",mtx[0]); printf("%c[0m ",0x1b); } else if (doprint==3 && path[slen*mcnt]) { printf(" %5s %d %5s ", "skip", a2oct(a2oct(TOKEN_ANGLE(m->token))), motionTokenStr(m->token)); printColor(ignoreMotion); printf("%4d %4d%c[0m\n",ignoreMotion,val,0x1b); } else if (doprint == -1) { path[slen*mcnt] = '^'; } for (scnt=1, s=spellTokens; *s; scnt++, s++) { char *src = "\\"; compareToken(&ignoreMotion, &ignoreSpell, &match, *s, m->token); val = match + corner; if (val > ignoreMotion + mtx[scnt]) { val = ignoreMotion + mtx[scnt]; src="^"; } if (val > ignoreSpell + mtx[scnt-1]) { val = ignoreSpell + mtx[scnt-1]; src="<"; } if (doprint==2) { if (path[slen*mcnt+scnt]) { printColor(val-lastval); lastval = val; } printf("%s%-4d", src,val); printf("%c[0m ",0x1b); } else if (doprint==3 && path[slen*mcnt+scnt]) { int delta = 1000; switch(src[0]) { case '^': printf(" %5s %d %5s ", "skip", a2oct(a2oct(TOKEN_ANGLE(m->token))), motionTokenStr(m->token)); delta = ignoreMotion; break; case '<': printf(" %5s %d %5s ", spellTokenStr(*s), a2oct(a2oct(TOKEN_ANGLE(*s))), "skip"); delta = ignoreSpell; break; case '\\': printf(" %5s %d %d %5s ", spellTokenStr(*s), a2oct(a2oct(TOKEN_ANGLE(*s))), a2oct(a2oct(TOKEN_ANGLE(m->token))), motionTokenStr(m->token)); delta = match; break; default: printf(" %5s %5s ", "????", "????"); break; } printColor(delta); printf("%4d %4d%c[0m\n",delta,val,0x1b); } else if (doprint==-1) { path[slen*mcnt+scnt] = src[0]; } corner = mtx[scnt]; mtx[scnt] = val; } } if (doprint==2) { printf("\n"); } else if (doprint == -1) { int i; int mlen = mcnt; // // find path // path[0] = '*'; scnt--; mcnt--; while(scnt>=0 && mcnt>=0) { int c = path[slen*mcnt+scnt]; path[slen*mcnt+scnt] = '*'; switch(c) { case '<': scnt--; break; case '^': mcnt--; break; case '\\': case '*': mcnt--; scnt--; break; } } for (i=0; i<mlen*slen; i++) { if (path[i] != '*') path[i] = 0; } } if (doprint>0 && doprint<3) { printf("Score vs %-25s = %8d\n",spell->name,val); } spell->score = val; return val; } typedef struct SpellCreateInfoRec { int lastAngle; int prevCircleCnt; } SpellCreateInfo; //=========================================================================== // spellInit() //=========================================================================== void spellInit(SpellCreateInfo *si, int startAngle) { memset(si,0,sizeof(*si)); si->lastAngle = startAngle; } //=========================================================================== // spellCircleSub() //=========================================================================== unsigned char *spellCircleSub(unsigned char *t, int dir, int *oct, int optional) { static int table_cw[8] = { 6,7,0,1,2,3,4,5 }; static int table_ccw[8] = { 2,3,4,5,6,7,0,1 }; int *table = dir<0 ? table_cw : table_ccw; if (optional) { *(t++) = TOKEN_CREATE(SSHP_OCIRCLE, dir, oct2a(table[*oct])); } else { *(t++) = TOKEN_CREATE(SSHP_CIRCLE, dir, oct2a(table[*oct])); } *oct = (*oct + dir) & 7; return t; } //=========================================================================== // spellCircle() //=========================================================================== unsigned char *spellCircle(unsigned char *t, SpellCreateInfo *si, int cnt) { int oct = a2oct(si->lastAngle); int dir = 1; int prevdir; int cnt0 = 0, cnt1 = 0, cnt2 = 0; if (cnt < 0) { dir = -1; cnt = -cnt; } // // Circles always end with // - lastAngle pointing the way it is supposed to and // - 2nd to last optional circle pulse perpendicular to end direction // // For example, if end angle is oct==2 (right) // tokens = ... CW4 CW3 CW2 oCW1 oCW0 oCW7 // si->lastAngle = oct2a(oct); switch(TOKEN_SHAPE(t[-1])) { case SSHP_PAUSE: *(t++) = TOKEN_CREATE(SSHP_OPULSE, 0, oct2a(oct)); oct = (oct - dir) & 7; cnt0 = 1; cnt1 = 2+8-1-2 + (8*(cnt-1)); cnt2 = 3; // NOTE: same lastAngle break; case SSHP_CIRCLE: case SSHP_OCIRCLE: prevdir = TOKEN_DIR(t[-1]); if (prevdir == dir) { t -= 3; oct = (oct - prevdir) & 7; cnt0 = 0; cnt1 = 2 + 8 - 2 + (8*(cnt-1)); cnt2 = 3; // NOTE: same lastAngle } else { oct = (oct + 4) & 7; *(t++) = TOKEN_CREATE(SSHP_OPULSE, 0, oct2a(oct)); *(t++) = TOKEN_CREATE(SSHP_OPULSE, 0, oct2a((oct+prevdir)&7)); *(t++) = TOKEN_CREATE(SSHP_OPULSE, 0, oct2a(oct)); oct = (oct - dir) & 7; cnt0 = 2; cnt1 = 2+8-2-2 + (8*(cnt-1)); cnt2 = 3; // circlSlop=5 si->lastAngle = oct2a(oct); } break; case SSHP_OPULSE: case SSHP_PULSE: oct = (oct - dir) & 7; cnt0 = 3; cnt1 = 2+8-3-2 + (8*(cnt-1)); cnt2 = 3; // NOTE: same lastAngle break; default: fatalError("Bad token in spellCircle() \n"); } while(cnt0--) { t = spellCircleSub(t, dir, &oct, 1); } while(cnt1--) { t = spellCircleSub(t, dir, &oct, 0); } while(cnt2--) { t = spellCircleSub(t, dir, &oct, 1); } si->prevCircleCnt = cnt; return t; } //=========================================================================== // spellPulse() //=========================================================================== unsigned char *spellPulse(unsigned char *t, SpellCreateInfo *si, int oct) { int revoct = (oct + 4) & 7; int optional = 0; int dir, octc, octprev = a2oct(si->lastAngle); int cnt; switch(TOKEN_SHAPE(t[-1])) { case SSHP_PAUSE: *(t++) = TOKEN_CREATE(SSHP_OPULSE,0,oct2a(oct)); break; case SSHP_OPULSE: case SSHP_PULSE: // // same direction as last pulse? // if (revoct == octprev) { optional = 1; *(t++) = TOKEN_CREATE(SSHP_OPULSE,0,oct2a(oct)); // // opposite direction of previous // } else if (oct == octprev) { break; // // some other angle (less) // } else if (odiff(oct,octprev) > 0) { while(octprev != oct) { t = spellCircleSub(t, 1, &octprev, 1); } } else { while(octprev != oct) { t = spellCircleSub(t, -1, &octprev, 1); } } break; case SSHP_CIRCLE: case SSHP_OCIRCLE: dir = TOKEN_DIR(t[-1]); octc = a2oct(si->lastAngle); //printf("octc=%d\n",octc); // t now points to the CW2 in example above t -= 4; //printf("t[]=%02x\n",*t); // oct now points up (4) in example above octc = (octc - dir * 2) & 7; cnt = -1; //printf("octc=%d cnt=%d\n",octc,cnt); if (si->prevCircleCnt > 1) { t -= 1; octc = (octc - dir) & 7; cnt -= 1; } //printf("t[]=%02x\n",*t); //printf("octc=%d cnt=%d\n",octc,cnt); //printf("S octc(%d) +dir(%d) !=? oct=%d\n",octc,dir,oct); while(((octc+dir)&7) != oct) { //printf("+ octc(%d) +dir(%d) !=? oct=%d\n",octc,dir,oct); t = spellCircleSub(t, dir, &octc, 0); cnt++; } //printf("E octc(%d) +dir(%d) !=? oct=%d\n",octc,dir,oct); // // if less than full circle add an extra optional circle // if (cnt < 0) { //printf("EXTRA\n"); for (cnt=0; cnt<8; cnt++) { t = spellCircleSub(t, dir, &octc, 1); } } //printf("2 octc=%d\n",octc); t = spellCircleSub(t, dir, &octc, 1); //printf("1 octc=%d\n",octc); t = spellCircleSub(t, dir, &octc, 1); //printf("0 octc=%d revoct=%d\n",octc,revoct); break; default: fatalError("Bad token in spellCircle() \n"); } if (optional) { *(t++) = TOKEN_CREATE(SSHP_OPULSE,0,oct2a(revoct)); } else { *(t++) = TOKEN_CREATE(SSHP_PULSE,0,oct2a(revoct)); } #if 0 *(t++) = TOKEN_CREATE(SSHP_OPULSE,0,oct2a(oct)); #endif si->lastAngle = oct2a(revoct); si->prevCircleCnt = 0; return t; } //=========================================================================== // spellPause() //=========================================================================== unsigned char *spellPause(unsigned char *t, SpellCreateInfo *si) { *(t++) = TOKEN_CREATE( SSHP_PAUSE, 0, 0); si->prevCircleCnt = 0; return t; } //=========================================================================== // createSpell() //=========================================================================== int createSpell(Spell *s, int startAngle) { SpellCreateInfo si[1]; unsigned char *t = s->tokens; const char *p; int oct; spellInit(si,startAngle); #define START_ANGLE_FROM_SPELL 1 #if START_ANGLE_FROM_SPELL startAngle = -1; for (p=s->phonemes; *p; p++) { switch(*p) { case 'e': case 'i': case 'a': case 'o': case 'u': case 'y': case ' ': break; case 'd': startAngle = oct2a(4); break; case 'k': startAngle = oct2a(2); break; case 'g': startAngle = oct2a(0); break; case 'f': startAngle = oct2a(6); break; case 'h': startAngle = oct2a(3); break; case 's': startAngle = oct2a(1); break; case 'm': startAngle = oct2a(7); break; case 'l': startAngle = oct2a(5); break; default: fatalError("ERROR: BAD PHONEME CHARACTER: %c\n in '%s'\n", *p,s->phonemes); } if (startAngle >= 0) { si->lastAngle = startAngle; break; } } #endif *(t++) = TOKEN_CREATE( SSHP_PAUSE,0,0); for (p=s->phonemes; *p; p++) { switch(*p) { case 'e': t = spellCircle(t,si,+2); break; case 'i': t = spellCircle(t,si,+3); break; case 'a': t = spellCircle(t,si,-1); break; case 'o': t = spellCircle(t,si,-2); break; case 'u': t = spellCircle(t,si,-3); break; case 'y': t = spellCircle(t,si,+1); break; case 'd': t = spellPulse(t,si,4); break; case 'k': t = spellPulse(t,si,2); break; case 'g': t = spellPulse(t,si,0); break; case 'f': t = spellPulse(t,si,6); break; case 'h': t = spellPulse(t,si,3); break; case 's': t = spellPulse(t,si,1); break; case 'm': t = spellPulse(t,si,7); break; case 'l': t = spellPulse(t,si,5); break; case ' ': t = spellPause(t,si); break; default: fatalError("ERROR: BAD PHONEME CHARACTER: %c\n in '%s'\n", *p,s->phonemes); } if (t-s->tokens > sizeof(s->tokens)-10) { fprintf(stderr,"\n\n\n"); fprintf(stderr,"ERROR: SPELL TOO LONG:\n"); fprintf(stderr," in '%s'\n", s->phonemes); fprintf(stderr,"\n\n\n"); exit(1); } } oct = a2oct(si->lastAngle); oct = (oct+4)&7; *(t++) = TOKEN_CREATE(SSHP_OPULSE,0,oct2a(oct)); //*(t++) = TOKEN_CREATE(SSHP_WILD, 0, 0); //*(t++) = TOKEN_CREATE(SSHP_WILD, 0, 0); *t = 0; return t - s->tokens; } //=========================================================================== // spellLen() - find # of tokens in spell //=========================================================================== int spellLen(Spell *s) { unsigned char *t = s->tokens; while(*t) t++; return t-s->tokens; } //=========================================================================== // buildSpell() - //=========================================================================== int buildSpell(Spell *s, int startAngle) { if (s->phonemes[0]) { createSpell(s, startAngle); } if (!s->tokens[0]) { s->tokens[0] = TOKEN_CREATE(SSHP_PAUSE, 0, 0); s->tokens[1] = 0; } return spellLen(s); } //=========================================================================== // checkSpells() //=========================================================================== void checkSpells(Spell *slist, Motion *mlist, int mcnt) { Motion *m, *mp; char *path; Spell *s, *best = 0, *best2=0; int scnt = 0; int startAngle = 0; // // ignore leading pause(s) // while(mlist && TOKEN_SHAPE(mlist->token) == MSHP_PAUSE) mlist = mlist->c_next; // // ignore trailing pause(s) // for (mp=m=mlist; m; m=m->c_next) { if (TOKEN_SHAPE(m->token) != MSHP_PAUSE) { mp = m; } } mp->c_next = 0; if (!mlist) return; // // find start angle // #if 0 for (m=mlist; m; m=m->c_next) { int shape = TOKEN_SHAPE(m->token); if (shape == MSHP_PULSE || shape == MSHP_PULSE_PLUS) { startAngle = TOKEN_ANGLE(m->token); break; } } #else startAngle = TOKEN_ANGLE(mlist->token); #endif // // count len of max spell // for (s=slist; s->name; s++) { int len; len = buildSpell(s, startAngle); if (len > scnt) { scnt = len; } } scnt++; path = malloc((mcnt+1) * scnt); for (s=slist; s->name; s++) { memset(path,0,mcnt*scnt); scoreSpell(s,mlist,path,-1); if (!OPT_silent) { // // 2nd time with printing // scoreSpell(s,mlist,path,2); scoreSpell(s,mlist,path,3); } if (!best || best->score > s->score) { best = s; } } free(path); // // find 2nd best // best2 = 0; for (s=slist; s->name; s++) { if (s==best) continue; if (!best2) best2 = s; if (best2->score > s->score) { best2 = s; } } printf("\nRESULT:Scores\n"); for (s=slist; s->name; s++) { printf("RESULT: %s %05d %s (%s)\n", s==best ? "*": s==best2 ? "+":" ", s->score, s->name, s->phonemes ? s->phonemes : ""); } } //=========================================================================== // main() //=========================================================================== int main(int argc, char *argv[]) { Spell *slist = spells; Spell *s; Motion mlist[CNT_MAX]; int mcnt=0; char **argp; memset(mlist,0,sizeof(mlist)); for(argp=&argv[1]; *argp; argp++) { if (!strcmp(*argp,"-s")) { OPT_silent=1; } else if (!strcmp(*argp,"-q")) { OPT_quick=1; } else { for (s=slist; s->name; s++) { if (!strcmp(*argp,s->name)) { slist = s; s[1].name = 0; break; } } } } mcnt = get(stdin,mlist,mlist+(sizeof(mlist)/sizeof(mlist[0]))); if (mcnt) { initialPrint(mlist); look(mlist,mcnt); if (!OPT_quick) { checkSpells(slist, mlist,mcnt); } } return 0; } |
This file Copyright (C) 2006 by Nathan (Acorn) Pooley
Go to TOP Wand page
Go to Acorn's personal webpage
Go to Hogwarts website: www.gotohogwarts.com
Snout: www.snout.org/game
Gadgets of Justice Unlimited
Snout GC (Wiki)
Snout Wiki
File created by do_doc at Wed May 30 03:26:56 PDT 2007