//#define CLI 1 #ifdef CLI #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <time.h> #define IN_ROM #else #include <vectrex.h> #include "controller.h" #define TEXT_SCALE (0x44) #include <assert.h> #define IN_ROM __attribute__ ((section(".text"))) #define NULL 0 #define EOF (-1) #endif // ########################################################################### // 0 and smaller terminates! int xstrlen (const char *s) { int c = 0; while ((signed int) (*(s)++) > 0) c++; return c; } const char matrix[6][6] = { // 1 block, 6 down, 5 across+1 for \x80 {'A', 'B', 'C', 'D', 'E', 0x80}, {'F', 'G', 'H', 'I', 'J', 0x80}, {'K', 'L', 'M', 'N', 'O', 0x80}, {'P', 'Q', 'R', 'S', 'T', 0x80}, {'U', 'V', 'W', 'X', 'Y', 0x80}, {'Z', '<', 'O', 'K', '>', 0x80} }; extern void syncPrintStrd (const int a, const int b, const void *u); #define xPrint_Str_d syncPrintStrd char *get_word (int screen_y) { int y; long int cx, cy; static unsigned int next = 0; static char input_line[7] = { ' ', ' ', ' ', ' ', ' ', 0x80, '\0' }; char *input; input = &input_line[1]; // extra space for bug or could add prompt if (button_1_3_pressed ()) {if (next) next -= 1;} // B3 is erase input[next] = 0x80; input[next+1] = '\0'; cx = (Vec_Joy_1_X + 128) / (255 / 6) - 1; // default center position cy = (-Vec_Joy_1_Y + 127) / (255 / 6) - 2; if (cx < 0) cx = 0; if (cx > 4) cx = 4; if (cy < 0) cy = 0; if (cy > 5) cy = 5; if ((button_1_4_pressed ())) { // B4 is accept if ((cy == 5) && (cx > 0)) { // accept word if (next == 4) { // if all 4 letters entered next = 0; // reset for next word to be input return input; } } else { // accept letter if (next < 4) { // if there is room input[next++] = matrix[cy][cx]; input[next] = (char) 0x80; input[next+1] = '\0'; } } } dp_VIA_t1_cnt_lo = TEXT_SCALE; // scale Reset0Ref (); Intensity_a (0x4f); // Display the letters of the word entered so far: xPrint_Str_d (120, -100, input_line); // and draw the choices for (y = 0; y <= 5; y++) xPrint_Str_d (screen_y + (5 - y) * 20 - 60, - 60, matrix[y]); Reset0Ref (); // Highlight the cursor Intensity_a (0x2f); #define SQUARESIZE 15 if ((cy == 5) && (cx > 0)) { // the 'enter' box Moveto_d (screen_y + (5 - (int) cy) * 20 - 60 + 3, 20 - 60 + 10); Draw_Line_d (0, SQUARESIZE * 5 + 6); Draw_Line_d (-SQUARESIZE, 0); Draw_Line_d (0, -(SQUARESIZE * 5 + 6)); Draw_Line_d (SQUARESIZE, 0); } else { Moveto_d (screen_y + (5 - (int) cy) * 20 - 60 + 3, (int) cx * 20 - 60 + 10); Draw_Line_d (0, SQUARESIZE); Draw_Line_d (-SQUARESIZE, 0); Draw_Line_d (0, -SQUARESIZE); Draw_Line_d (SQUARESIZE, 0); } return NULL; // until a full word has been entered... } // ########################################################################### #define uint16_t unsigned long #define WORDS 2547 // The word list has been sorted (roughly) by frequency of the words // in common use. (The sort program is in ~/src/IPA/spell/sort-by-freq.c) // This way, the game can make sure that the words it suggests are // not too obscure. #define SIMPLE_WORDS 1000 // This array is a bit vector in which we mark whether a word is // compatible with the scoring so far - if it isn't, that word is // eliminated from the set of remaining possible solutions. // This is the only data of any significant size that needs to // be in RAM - all the other large arrays are stored in ROM. static char eliminated[WORDS / 8 + 1]; const char const *word[WORDS] IN_ROM = { "THAT", "THIS", "WITH", "FROM", "YOUR", "HAVE", "MORE", "WILL", "HOME", "PAGE", "FREE", "TIME", "THEY", "SITE", "WHAT", "NEWS", "ONLY", "WHEN", "HERE", "ALSO", "HELP", "VIEW", "BEEN", "WERE", "SOME", "LIKE", "THAN", "FIND", "DATE", "BACK", "LIST", "NAME", "JUST", "OVER", "YEAR", "INTO", "NEXT", "USED", "WORK", "LAST", "MOST", "DATA", "MAKE", "THEM", "POST", "CITY", "SUCH", "BEST", "THEN", "GOOD", "WELL", "INFO", "HIGH", "EACH", "VERY", "BOOK", "READ", "NEED", "MANY", "USER", "SAID", "DOES", "MAIL", "FULL", "LIFE", "KNOW", "DAYS", "PART", "REAL", "ITEM", "MUST", "MADE", "LINE", "SEND", "TYPE", "TAKE", "AREA", "WANT", "LONG", "CODE", "SHOW", "EVEN", "MUCH", "SIGN", "FILE", "LINK", "OPEN", "CASE", "SAME", "BOTH", "GAME", "CARE", "DOWN", "SIZE", "SHOP", "TEXT", "RATE", "FORM", "LOVE", "JOHN", "MAIN", "CALL", "SAVE", "CARD", "JOBS", "FOOD", "SALE", "TEEN", "ROOM", "JOIN", "WEST", "LOOK", "LEFT", "TEAM", "WEEK", "NOTE", "LIVE", "PLAN", "COST", "TEST", "COME", "CART", "PLAY", "LESS", "PARK", "SIDE", "GIVE", "SELL", "BODY", "EAST", "CLUB", "ROAD", "GIFT", "HARD", "FOUR", "BLUE", "EASY", "STAR", "HAND", "KEEP", "BABY", "TERM", "FILM", "HEAD", "CELL", "SELF", "AWAY", "ONCE", "SURE", "CARS", "TELL", "ABLE", "GOLD", "ARTS", "PAST", "FIVE", "UPON", "SAYS", "LAND", "DONE", "EVER", "WORD", "BILL", "TALK", "NUDE", "KIDS", "TRUE", "ELSE", "MARK", "ROCK", "TIPS", "PLUS", "AUTO", "EDIT", "FAST", "FACT", "UNIT", "MEET", "FEEL", "BANK", "RISK", "TOWN", "GIRL", "TOYS", "GOLF", "LOAN", "WIDE", "SORT", "HALF", "STEP", "NONE", "LAKE", "FIRE", "CHAT", "LOSS", "FACE", "BASE", "NEAR", "STAY", "TURN", "MEAN", "KING", "COPY", "DRUG", "PICS", "CASH", "SEEN", "PORT", "STOP", "SOON", "HELD", "MIND", "LOST", "TOUR", "MENU", "HOPE", "WISH", "ROLE", "CAME", "FINE", "HOUR", "BUSH", "HUGE", "KIND", "MOVE", "LOGO", "NICE", "SENT", "BAND", "LEAD", "WENT", "MODE", "FUND", "MALE", "TOOK", "SONG", "LATE", "FALL", "IDEA", "TOOL", "HILL", "MAPS", "DEAL", "HOLD", "SAFE", "FEED", "HALL", "ANTI", "SHIP", "PAID", "HAIR", "TREE", "THUS", "WALL", "WINE", "VOTE", "WAYS", "RULE", "TOLD", "FEET", "SEXY", "DOOR", "COOL", "USES", "JAVA", "PASS", "FEES", "SKIN", "RING", "BOYS", "DEEP", "REST", "POOL", "MINI", "FISH", "PACK", "BORN", "RACE", "RAPE", "DEBT", "CORE", "SETS", "WOOD", "RENT", "DARK", "HOST", "FAIR", "GETS", "DEAD", "MIKE", "TRIP", "POOR", "EYES", "FARM", "LORD", "HEAR", "GOES", "WIFE", "HITS", "ZONE", "JACK", "FLAT", "FLOW", "PATH", "LAWS", "SKIP", "DIET", "ARMY", "GEAR", "LOTS", "FIRM", "JUMP", "BALL", "GOAL", "SOLD", "WIND", "PALM", "PAIN", "ORAL", "FORD", "EDGE", "ROOT", "PINK", "SHOT", "COLD", "FOOT", "MASS", "HEAT", "WILD", "MISS", "TASK", "SOFT", "FUEL", "WALK", "WAIT", "ROSE", "PICK", "LOAD", "TAGS", "GUYS", "COCK", "DROP", "RICH", "SEEM", "HIRE", "GAVE", "ONES", "TITS", "RANK", "DIED", "INCH", "SNOW", "CAMP", "FILL", "GONE", "FORT", "GENE", "DISC", "BOAT", "ICON", "ENDS", "CAST", "FELT", "SOUL", "AIDS", "FLAG", "ATOM", "IRON", "VOID", "DISK", "DESK", "VICE", "DUTY", "BEAR", "GAIN", "LACK", "KNEW", "ZOOM", "BLOW", "CLIP", "WIRE", "TAPE", "ACID", "CENT", "NULL", "ZERO", "ROLL", "BATH", "FONT", "BETA", "FAIL", "JAZZ", "BAGS", "WEAR", "RARE", "BARS", "DUAL", "RISE", "BIRD", "LADY", "DELL", "SEAT", "BIDS", "TOLL", "CAPE", "MINE", "WHOM", "MATH", "DOGS", "MOON", "FEAR", "WARS", "KEPT", "BEAT", "ARMS", "HIDE", "SLOW", "NINE", "SPOT", "GROW", "RAIN", "ONTO", "BASS", "HOLE", "PETS", "RIDE", "PAIR", "RUNS", "YEAH", "EVIL", "EURO", "PEAK", "DICK", "SALT", "BELL", "LANE", "KILL", "AGES", "PLUG", "COOK", "BIKE", "LOSE", "SEEK", "KITS", "SOIL", "MATT", "EXIT", "KEYS", "WAVE", "HOLY", "ACTS", "MESH", "DEAN", "POLL", "BOND", "JEAN", "VISA", "PURE", "HELL", "LENS", "DRAW", "WARM", "SUCK", "BABE", "CREW", "LEGS", "REAR", "NODE", "LOCK", "MILE", "BOWL", "TANK", "NAVY", "DISH", "SLOT", "GRAY", "DEMO", "HATE", "RICE", "LOOP", "VARY", "MILK", "BOOT", "PUSH", "DEAR", "BEER", "EARN", "TWIN", "BITS", "SUIT", "CHIP", "CHAR", "ECHO", "GRID", "PULL", "NICK", "PLOT", "PUMP", "EXAM", "BEDS", "GREY", "BOLD", "SCAN", "AGED", "BULK", "CUTE", "PARA", "SEED", "PEER", "MEAT", "BANG", "BONE", "BUGS", "GATE", "TONE", "BUSY", "NECK", "WING", "TINY", "RAIL", "TUBE", "BELT", "LUCK", "DIAL", "GANG", "CAKE", "SEMI", "CAFE", "TILL", "SHOE", "SAND", "SEAL", "LIES", "PIPE", "DECK", "THIN", "SICK", "DOSE", "LETS", "CATS", "FOLK", "OKAY", "HIST", "LIFT", "MALL", "FELL", "YARD", "POUR", "DUST", "BUTT", "KENT", "ADDS", "WARD", "ROOF", "KISS", "RUSH", "YOGA", "LAMP", "GLAD", "WINS", "RACK", "BOSS", "SOLO", "TALL", "NOVA", "WAKE", "DRUM", "EASE", "ORGY", "TABS", "PINE", "TEND", "GULF", "RICK", "HUNT", "MILL", "BURN", "LABS", "SOLE", "LAID", "CLAY", "WEAK", "WISE", "ODDS", "SONS", "LEAF", "SILK", "WOLF", "FITS", "KICK", "MEAL", "HURT", "SLIP", "CUTS", "MARS", "CAPS", "PILL", "META", "MINT", "SPIN", "WASH", "AIMS", "SOAP", "AXIS", "GUNS", "HERO", "PUNK", "DUKE", "PACE", "WAGE", "DAWN", "COAT", "DOLL", "REED", "MICE", "TEMP", "VAST", "WRAP", "MOOD", "QUIZ", "BEAM", "TOPS", "SHUT", "THOU", "MASK", "COAL", "LION", "BEEF", "HATS", "SURF", "HOOK", "CORD", "CROP", "SING", "TONS", "HANG", "DAMN", "HOOD", "FAME", "EGGS", "RUBY", "STEM", "DREW", "TUNE", "CORN", "PUTS", "GREW", "TREK", "TIES", "BRAD", "JURY", "TAIL", "LAWN", "SOUP", "BYTE", "NOSE", "TRIM", "QUIT", "LUNG", "SEES", "BULL", "COLE", "MART", "TALE", "DOCS", "COIN", "FAKE", "CURE", "ARCH", "BOMB", "HARM", "DEER", "OVEN", "NOON", "MATE", "CHEF", "ISLE", "SLIM", "SPEC", "MIDI", "TIED", "DALE", "BOOB", "OILS", "SEPT", "UNTO", "PAYS", "LANG", "STUD", "FOLD", "SLUT", "POLE", "BEND", "GLEN", "LIPS", "POND", "TIRE", "CHAD", "JOSH", "DRAG", "RIPE", "RELY", "NUTS", "NAIL", "SPAN", "JOKE", "PADS", "INNS", "CUPS", "FOAM", "POEM", "ASKS", "BEAN", "BIAS", "SWIM", "LOUD", "RATS", "STAT", "THEE", "RUTH", "PRAY", "POPE", "JEEP", "BARE", "HUNG", "MONO", "TILE", "CIAO", "KNEE", "PREP", "PROS", "CANT", "DUCK", "DIVE", "RAID", "VOLT", "DIRT", "GEEK", "SINK", "GRIP", "WATT", "PINS", "POLO", "HORN", "FROG", "LOGS", "SNAP", "SWAP", "FLIP", "BUZZ", "NUKE", "BOOM", "CALM", "FORK", "TROY", "SIMS", "TRAY", "SAGE", "CAVE", "WOOL", "EYED", "GRAB", "OOPS", "TRAP", "FOOL", "DIES", "JAIL", "LACE", "UGLY", "HART", "ROWS", "GODS", "POLY", "EARS", "FIST", "MERE", "CONS", "TAXI", "WORN", "SHAW", "EXPO", "DENY", "TRIO", "CUBE", "RUGS", "CRAP", "FATE", "OVAL", "TIER", "EARL", "CITE", "MESS", "ROPE", "DUMP", "HOSE", "PUBS", "MILD", "CLAN", "SYNC", "MESA", "HULL", "SHED", "MEMO", "TIDE", "FUNK", "REEL", "BIND", "RAND", "BUCK", "ACRE", "LOWS", "AQUA", "PEST", "REEF", "JILL", "SOFA", "TENT", "HACK", "DARE", "HAWK", "LAMB", "JUNK", "POET", "EPIC", "SAKE", "LEAN", "DUDE", "ALTO", "GORE", "CULT", "DASH", "CAGE", "PING", "FLUX", "RAGE", "RAYS", "ACNE", "UNDO", "HALO", "GAYS", "EXEC", "DOOM", "BITE", "MYTH", "WEED", "DICE", "QUAD", "DOCK", "MODS", "HINT", "BUYS", "PORK", "BARN", "FARE", "BALD", "MOLD", "DAME", "HERB", "IDLE", "COVE", "FLEX", "HASH", "LAZY", "CARB", "PENS", "WORM", "DEAF", "MATS", "MIME", "KEEN", "PEAS", "OWNS", "ZINC", "GURU", "LEVY", "BRAS", "PALE", "GAPS", "TEAR", "NEST", "GALE", "IDOL", "MOSS", "CORK", "DOME", "HEEL", "YANG", "DUMB", "FEAT", "GLOW", "OAKS", "NORM", "WARE", "JADE", "FOUL", "KENO", "SEAS", "POSE", "GOAT", "SAIL", "BOLT", "GAGE", "URGE", "NEON", "OURS", "LONE", "COPE", "LIME", "KIRK", "SPAS", "JETS", "YARN", "KNIT", "PIKE", "BENT", "MAMA", "COIL", "LILY", "JOEY", "TILT", "BEAD", "LEAK", "BULB", "IRIS", "STIR", "PILE", "WADE", "PONY", "LEAP", "SWAN", "SCAT", "NETS", "BASH", "NEAT", "BUMP", "AUNT", "CROW", "GRAM", "SITS", "TOES", "BUST", "COLA", "GEMS", "OUTS", "FOIL", "AMPS", "TICK", "VANS", "GLUE", "CONE", "OLDS", "RAMP", "PEAR", "CLUE", "DUFF", "SCAM", "BECK", "TOME", "PROF", "SINS", "HATH", "PROP", "MAID", "HAHA", "RODS", "PIGS", "MAYA", "DEED", "PAPA", "WARN", "COPS", "PESO", "VENT", "DOTS", "MUGS", "VASE", "HOMO", "PIER", "SAGA", "GRAN", "MAYO", "LISP", "CHIN", "WONT", "HUBS", "SODA", "TOMB", "PROM", "CUBS", "PULP", "POTS", "SLAM", "CRIB", "NOUN", "CRAB", "HIKE", "BORE", "COWS", "PEEL", "BAKE", "HEAL", "TOTE", "SOUR", "SOCK", "BAIL", "TEES", "MIST", "VERB", "CHIC", "VEST", "TENS", "PUMA", "RANT", "GILL", "RUDE", "SANG", "CURL", "DELI", "VINE", "VALE", "LIMO", "RUST", "AVID", "BETS", "FADE", "MONK", "POOH", "TORN", "HECK", "BARK", "LYNX", "ROMS", "ODOR", "FLEW", "APEX", "CURB", "DECO", "COKE", "WEBS", "PROD", "CANE", "FURY", "WORE", "DUES", "GIGS", "PLEA", "PREY", "LICK", "NESS", "WHIP", "PROG", "BINS", "BOUT", "HANK", "FOND", "SORE", "FIAT", "NOEL", "CANS", "AIDE", "LIEU", "REDS", "KNOB", "DOVE", "MACK", "SUNG", "ALLY", "HOLT", "DULL", "BEES", "SIGH", "MOCK", "BATS", "MELT", "FAUX", "PANT", "HYPE", "RITE", "TURF", "BERG", "MUSE", "TYNE", "LUST", "LUNA", "LIEN", "VEIN", "HALE", "TIFF", "BAIT", "DENT", "MACS", "SUMS", "LAME", "FUSE", "POPS", "AMID", "KNOT", "TATE", "COOP", "KRIS", "REGS", "PLUM", "LOFT", "LUMP", "HALT", "AERO", "BURY", "DUCT", "LEND", "PANS", "IONS", "RAMS", "GOWN", "RUIN", "TUNA", "WIPE", "HAUL", "DULY", "OBEY", "MARE", "KITE", "HEAP", "EATS", "FLEA", "PALS", "HAIL", "HERD", "CALF", "RAVE", "JERK", "FLAP", "DIVA", "TAPS", "OATH", "GALA", "TANG", "RIOT", "FATS", "RITZ", "LUSH", "GRIM", "FLOP", "TOSS", "PITY", "WOKE", "CUFF", "REPS", "EDDY", "CUES", "COLT", "OFFS", "JARS", "HIPS", "WIGS", "HUNK", "CHAP", "TELE", "HARP", "PHAT", "TACK", "SACK", "PEEK", "SECS", "SUED", "TOBY", "OPAL", "TOON", "VIVA", "BLEW", "LAVA", "VAIL", "ENVY", "SHAH", "BOTS", "STAG", "RASH", "BOIL", "VAIN", "MAZE", "RODE", "AMEN", "WARP", "ZETA", "BREW", "KERN", "COUP", "FORE", "ALPS", "SUBS", "LIMB", "LIMP", "MUTE", "DART", "ROBE", "MAST", "COZY", "COMB", "ALAS", "CHOP", "ONYX", "HOOP", "NOPE", "DIRE", "GULL", "RIMS", "SHIN", "FLAW", "PANE", "VIBE", "TEAS", "ANON", "RIBS", "BARB", "HUNS", "AURA", "SECT", "NOUS", "MOLE", "OWED", "BUFF", "CLAD", "FLED", "ACES", "LIED", "BLOC", "HUGS", "OWLS", "PIMP", "GIMP", "HEMP", "INKS", "WINK", "FIFE", "STUB", "TORT", "DAMS", "MACH", "SPUR", "SKIS", "PACT", "LULU", "VITA", "IBIS", "MULE", "KIWI", "DUEL", "MEAD", "GONG", "BAYS", "GAZE", "HULK", "CYAN", "AXES", "HAZE", "PITS", "ANTS", "TUCK", "SLAB", "LURE", "KART", "LING", "TUBS", "MAGS", "HERS", "GRIN", "SPIT", "ACME", "ROVE", "CHOW", "ARIA", "DIRK", "SCAR", "DORM", "PIES", "SAWS", "DINE", "SLAP", "JAWS", "ANTE", "BRED", "TOUT", "HARE", "TORY", "VEIL", "PECK", "HELM", "JESS", "JAYS", "CHEW", "TEAK", "SANE", "DUNE", "MANA", "LEST", "BLUR", "PUNT", "MOJO", "DIME", "CARP", "DUSK", "LENT", "ALOE", "PUFF", "CLAW", "TYRE", "WAND", "TACO", "WELD", "WRIT", "TYPO", "DAMP", "FERN", "LORE", "GYMS", "ARID", "JIVE", "SPUN", "LOCH", "BALM", "FIGS", "CHIT", "LAYS", "DRIP", "MANS", "PINT", "MAXI", "LIAR", "OPUS", "MAGE", "TEAL", "BARD", "REAP", "TIDY", "VETS", "BOWS", "BEAU", "RANG", "LAPS", "PONG", "VOWS", "SOAR", "FLEE", "WOES", "STEW", "HUSH", "LAMA", "AKIN", "DADS", "HAYS", "SOAK", "HYMN", "QUAY", "WEIR", "DRAM", "BURR", "SLUG", "LIRA", "JAMS", "DYES", "YELL", "FINS", "RAKE", "SUNS", "BUNK", "STAB", "DYKE", "SEAM", "OMIT", "DARN", "AMMO", "LINN", "VETO", "CLAM", "NERD", "GUTS", "BANS", "BUDS", "SIRE", "DING", "COMA", "THUG", "SHAM", "LOAF", "SKID", "POOP", "WHEY", "CURT", "MOTH", "MASH", "GERM", "ATOP", "KEMP", "PUCK", "MOOR", "LUBE", "SWAY", "TOAD", "EROS", "MALT", "PODS", "CLAP", "PAWS", "POKE", "DOPE", "KILN", "JOCK", "DYED", "WASP", "FUSS", "SWAT", "SINE", "BRAY", "ROAR", "GALL", "JUGS", "APES", "SLIT", "CINE", "BEEP", "TOMS", "SLID", "NANA", "RAFT", "BROW", "VARS", "FINK", "DEEM", "FLAX", "TART", "TRAM", "ICED", "BILE", "HEIR", "LOCO", "FEDS", "LOOM", "GRUB", "SLEW", "DUET", "OHMS", "MUCK", "HOAX", "WARY", "RIFF", "MACE", "LIDS", "PORE", "OILY", "WHOA", "JOYS", "GRIT", "NAYS", "SINH", "SUES", "TAME", "OATS", "WILT", "TING", "EMIT", "RINK", "NUMB", "SCOT", "PAVE", "AIRY", "HOBO", "HOPS", "AIRS", "DOLE", "WICK", "OWES", "PEAT", "TOFU", "TWAT", "SUNK", "PERM", "LAIR", "LACY", "WREN", "ARCS", "AYES", "HEED", "BOON", "PAWN", "TORE", "DUNK", "SNIP", "MUTT", "OUCH", "DIPS", "DIGS", "WOMB", "JOSS", "KOHL", "PUPS", "LIDO", "DAFT", "GILT", "TRAD", "TAXA", "SLED", "ELAN", "REFS", "COAX", "LEES", "ALUM", "DOTH", "PLOW", "SMUT", "FOES", "BLOT", "IMAM", "HOVE", "RIAL", "SEWN", "RIFT", "PEEP", "JUDO", "MAYS", "OBOE", "LOBE", "GOSH", "MICA", "LADS", "SUMO", "UREA", "ZEAL", "BONG", "GENT", "HIND", "ACHE", "YOKE", "TINS", "LOOT", "GASP", "TINT", "SILT", "LINT", "BLOB", "ROAM", "STUN", "TREY", "FANG", "WEEP", "GIGA", "ERGO", "MOAN", "SANK", "BALE", "SMOG", "KEEL", "FART", "COSY", "SEER", "VIAL", "HUFF", "GUST", "MUSK", "LICE", "SKIM", "RUNE", "WELT", "VEAL", "RAGS", "POSH", "MINK", "ITCH", "DILL", "RIGS", "MOOT", "AGAR", "REIN", "BUOY", "HIVE", "NEWT", "DUNG", "LARK", "HOES", "RUFF", "ZOOS", "SCUM", "BRAN", "FARO", "GIRO", "COTS", "FRET", "GUMS", "GLIB", "GEES", "VILE", "BRIO", "PERI", "LOCI", "HULA", "FOXY", "PUTT", "YEAS", "CRAM", "HENS", "HOGS", "FRAY", "GAGS", "RIPS", "SASH", "LIRE", "RAJA", "BOAR", "MITE", "SPAR", "REDO", "NOME", "BRAT", "WITS", "ANEW", "LOON", "HONE", "SIPS", "WORT", "NUNS", "TUBA", "JEST", "MORT", "REPO", "GNUS", "JOLT", "SKEW", "CYST", "FOWL", "PATE", "SNUG", "ORCA", "NOOK", "ROSY", "HOWL", "HOBS", "OGRE", "SPED", "YOGI", "PATS", "DOJO", "GAIT", "MEEK", "STOW", "BIBS", "CABS", "HUMP", "BEET", "GELD", "PEGS", "MEOW", "LASH", "ILLS", "OMEN", "BRIG", "TUFF", "CODA", "DEFY", "FOSS", "KILT", "WHIT", "COOS", "VINO", "CLOG", "YETI", "SILL", "BUNS", "NILS", "LAIN", "HOLM", "TOTS", "TORS", "FURL", "HOGG", "MUON", "AFAR", "FAWN", "ETCH", "FLUE", "EMIR", "MOBS", "GOUT", "RUBS", "BOBS", "BANE", "THAW", "EELS", "SHUN", "DAZE", "TROT", "WOOF", "DAVY", "WHAM", "BEGS", "MULL", "BODE", "URNS", "QUID", "KILO", "NODS", "PARR", "DORK", "SARI", "MITT", "YAWN", "FEUD", "BRUT", "GIST", "ZIPS", "TACT", "RIFE", "HUTS", "SILO", "ERAS", "MEND", "MUMS", "TERN", "LASS", "ROTA", "JUTE", "PRIM", "PANG", "SWAG", "OPTS", "MANO", "FURS", "WHIM", "PIED", "NIGH", "ALES", "SUMP", "ZEST", "WISP", "SIFT", "OOZE", "FUME", "BRAG", "MUFF", "SNAG", "YANK", "SHAG", "HUES", "LAGS", "SPAT", "ICES", "AHEM", "WAVY", "CRUX", "OBIT", "SLAG", "SKIT", "KELP", "VAMP", "IOTA", "BLED", "PITA", "SLUM", "FUZZ", "TOIL", "GARB", "PARS", "TWIG", "WEPT", "EDGY", "JIGS", "BURG", "ROOK", "PALL", "TRIG", "MOAT", "SWAM", "HAZY", "HOOF", "FRAG", "VISE", "LUTE", "PRAM", "BRIM", "CHUM", "GLUT", "NEVE", "SACS", "SOOT", "ROUX", "VANE", "MANE", "KINK", "RHEA", "SOWN", "BEAK", "RUNG", "TWAS", "LOAM", "ROMP", "CZAR", "MUSH", "FOAL", "GOGO", "NOES", "PAIL", "LOIN", "LEER", "NAVE", "HOWS", "LEEK", "PUSS", "OARS", "CLOT", "SOYA", "JOES", "MORN", "GLUG", "ROUT", "PLOY", "MAGI", "PUKE", "GLEE", "HAMS", "HOOT", "PINA", "BOTT", "KALE", "HUCK", "JUKE", "JINX", "TICS", "TORA", "FIDO", "AVER", "PUGS", "TALA", "COLS", "MILT", "WART", "NAPS", "GUSH", "OGLE", "BUSS", "HISS", "RUSK", "GORY", "BONY", "MOLL", "MEWS", "CASK", "BRIE", "OXEN", "BUMS", "MOPS", "NOTA", "FEND", "VEER", "NIPS", "DEBS", "GLOB", "REAM", "ORES", "BOLL", "SHIM", "IDES", "GNAT", "AMOK", "ARTY", "SMUG", "DONS", "YULE", "LUGS", "BATE", "PERT", "TSAR", "COSH", "BURP", "WERT", "CUSP", "BADE", "REVS", "YOLK", "BOOS", "CULL", "MAUL", "AHOY", "HAAR", "POMS", "YELP", "GYRO", "LUGE", "SEAR", "EGOS", "PARE", "VIOL", "TARP", "PUNY", "MISO", "FIZZ", "FOCI", "DRAB", "FLAK", "YUCK", "QUOD", "ABLY", "LARD", "HYPO", "SWAB", "RIND", "ROTE", "RUSE", "MUSS", "SPUD", "CROC", "ELMS", "FETA", "ONUS", "BIER", "LULL", "LINO", "SHEW", "ELKS", "TUTU", "RAPS", "ALMS", "BIFF", "SWOT", "ASPS", "MOTE", "WOLD", "BOAS", "IDEM", "HARK", "THUD", "WEDS", "PERK", "FIRS", "RUMP", "PENT", "SAGO", "RIVE", "TABU", "GAWK", "HOCK", "HEFT", "LEWD", "DUPE", "BOGS", "TOSH", "LOUP", "SWIG", "FETE", "DUNS", "FAIN", "PIPS", "SIRS", "COWL", "SLAT", "GOON", "PICA", "TAUT", "KOLA", "SNOB", "CRUD", "TINE", "RACY", "AWRY", "LODE", "SPAY", "TOKE", "CLEF", "PELT", "WADI", "GOOF", "ANKH", "DANK", "ZANY", "TOGA", "PUNS", "HILT", "ROAN", "NAGS", "WILY", "DODO", "COGS", "TALC", "POMP", "NOMS", "SPEW", "GULP", "LURK", "PEND", "TOOT", "SNOT", "HURL", "DORY", "NARY", "IBEX", "ORBS", "RAZZ", "ZING", "TOED", "SCAB", "PHEW", "WAIL", "CRAG", "TASS", "EVES", "MINX", "DENS", "QUIN", "PURR", "NITS", "OUST", "BASK", "GASH", "DUBS", "ODES", "WANE", "OYEZ", "FADS", "OVUM", "DENE", "SLAW", "NABS", "WHIG", "TUGS", "MELD", "LYRE", "DEFT", "HUSK", "HICK", "HONK", "TURD", "CUSS", "POUT", "MIRE", "NETT", "SAPS", "SHIV", "BALK", "SARK", "ROBS", "IDLY", "EWES", "GAST", "WAXY", "LOOS", "MIEN", "REDE", "ABET", "KERB", "CURD", "BARF", "BLIP", "ICKY", "DOSS", "SOWS", "WIMP", "MOOS", "ORYX", "YAMS", "REND", "KINE", "ROTS", "ROOD", "DADO", "WHET", "DOER", "SEEP", "SODS", "SOBS", "PURL", "SAWN", "MUDS", "WEAN", "JUJU", "DINK", "IMPS", "PUPA", "SUDS", "OKRA", "BREN", "SNUB", "PRAT", "DIMS", "DERM", "SCUD", "SOPS", "SLUR", "URIC", "TUSK", "TWEE", "SHOO", "SATE", "YORE", "SLOP", "BOZO", "TWOS", "HAKE", "GAOL", "TARN", "FAGS", "TARE", "GAGA", "FLAY", "FESS", "HOTS", "SETT", "ILEX", "WHEE", "AWED", "TWIT", "RUCK", "SLOG", "FLOG", "TOPI", "WILE", "DUDS", "DEET", "RIME", "GOAD", "SPRY", "COOT", "JABS", "OINK", "PEWS", "BRAE", "JOTS", "URSA", "PLOP", "GROG", "MELL", "RUNT", "CEDE", "TEEM", "BONK", "DUOS", "SUET", "INKY", "HEWN", "VOLE", "SYNE", "FLAN", "AXED", "JAGS", "QUIP", "SHOD", "IFFY", "SAKI", "WOVE", "BIDE", "BEVY", "FLIT", "DOUR", "KEGS", "NOSY", "DABS", "POSY", "GHEE", "VEND", "ABUT", "EONS", "LUFF", "TEAT", "DAIS", "PITH", "GAFF", "CHUG", "LAUD", "BUTS", "GOER", "PEED", "BODS", "PEAL", "COIR", "KOOK", "NOBS", "VATS", "TROD", "NAPE", "HOLS", "WEFT", "TEDS", "LASE", "GOOS", "GINS", "REEK", "WETS", "KENS", "HUMS", "VACS", "BUNG", "RAPT", "OTIC", "LEET", "PEES", "RASP", "DOZE", "WONK", "TATS", "DINT", "ELLS", "GAPE", "SONE", "WOWS", "BOLE", "CRAW", "TUFT", "TOFT", "FLAM", "NIBS", "AILS", "CUED", "SLOB", "GLUM", "HEMS", "SERF", "BOXY", "WOKS", "HUED", "HOAR", "JAMB", "WHYS", "FENS", "CADS", "ABED", "RUTS", "ULAN", "PROW", "SUSS", "DACE", "WAGS", "MAIM", "KUDU", "TUSH", "ESPY", "RUMS", "TIPI", "CURS", "ZITS", "GUNK", "VIES", "LOPE", "ERRS", "ROUP", "FAZE", "AJAR", "FOBS", "IRKS", "NOSH", "BYES", "LOUT", "METE", "WADS", "SWOP", "TOGS", "JIBE", "HAWS", "GOBS", "RAZE", "HASP", "WAIN", "PYRE", "APSE", "SOUK", "TOPE", "LORN", "NOCK", "TOWS", "DEWY", "WEAL", "KOAN", "PUCE", "EPEE", "STET", "TARS", "AMYL", "TEED", "YOBS", "DIBS", "EMUS", "YURT", "CAWS", "LADE", "WEND", "WIRY", "SNOG", "TUTS", "EXES", "DRAY", "HAFT", "IGLU", "FOGS", "DAWS", "LOTH", "TROW", "SIBS", "BLAB", "GYRE", "FRIT", "ACHY", "ARUM", "SAGS", "LATH", "WOOS", "GILD", "WINO", "WYLE", "LANK", "SKAT", "ACED", "PLOD", "FAUN", "HEBE", "TYRO", "RILL", "TAMP", "OAST", "GIRD", "GNAW", "POCK", "TYKE", "SCAG", "EBBS", "LAZE", "DRAT", "CLOD", "WAIF", "KITH", "SULK", "COBS", "DHOW", "KIPS", "DOLT", "RIDS", "KNAP", "ADZE", "CLEW", "EWER", "FLOE", "OLDY", "GUFF", "NUBS", "LILT", "WEES", "ASHY", "EFTS", "LOBS", "JOGS", "ZAPS", "DEWS", "DAUB", "ULNA", "ADIT", "MURK", "WIST", "COIF", "FLAB", "OUZO", "OSSA", "TOFF", "VAIR", "GADS", "KHAT", "YAKS", "SKUA", "VEEP", "CLOP", "WIVE", "ZAGS", "KINS", "TIKE", "GHAT", "BILK", "VIED", "SORB", "FIBS", "BOPS", "SNIT", "NOWT", "ERNE", "RUES", "DOTE", "ERGS", "SCOW", "MOWN", "PASH", "SEWS", "RILE", "NIDE", "PAWL", "NEAP", "KAPA", "ARKS", "RHOS", "MOKE", "FRAP", "WAFT", "JEER", "IMPI", "SKEE", "SWUM", "YAWL", "AGOG", "DOFF", "WYND", "HAGS", "EGAD", "JUTS", "GABS", "ETUI", "MOPE", "OGEE", "STOB", "MAWS", "BAWL", "WOAD", "BUSK", "SLOE", "LOPS", "ROUE", "YAWS", "TUNS", "ECUS", "LOLL", "CHAW", "TUFA", "JOWL", "ZONK", "KADI", "UTAS", "EGGY", "BOFF", "GELT", "TZAR", "CONK", "SKAG", "UNCO", "WYCH", "AVOW", "HEWS", "DOZY", "POKY", "ROIL", "MOWS", "OOHS", "STYE", "ZEBU", "MIFF", "BOYO", "GROT", "BYRE", "RAKI", "EKED", "GAMP", "HARL", "WHIN", "IDYL", "VAGI", "CORM", "WENS", "ULVA", "NEUK", "ULUS", "DINS", "BAWD", "FOPS", "HOED", "LOUR", "GIBE", "HADJ", "MAZY", "AWLS", "MOIL", "PHUT", "UVEA", "HIES", "SOTS", "UPAS", "HIED", "JAPE", "SKEG", "DUNT", "DUGS", "BRAW", "HODS", "YIPS", "RUED", "SUPS", "NARK", "PUDS", "YAPS", "OAFS", "ODIC", "TAWS", "FUGS", "IAMB", "TRUG", "GOYS", "ORRA", "FRUG", "PEKE", "PRIG", "GLEY", "JILT", "AUKS", "ILEA", "ALBS", "EKES", "KEEK", "CLOY", "GYBE", "OXID", "EYAS", "JOKY", "SPIV", "GAWP", "APED", "LYES", "AERY", "AWES", "TIVY", "SCUT", "YOWL", "SURD", "OOZY", "ZIGS", "PLEB", "FROW", "ENOW", "ZEES", "DRIB", "WINY", "JINK", "DRUB", "TUPS", "SHMO", "MUMP", "SMEW", "WOST", "SNED", "SILD", "NOGS", "SIZY", "GIRN", "DOPY", "SNIB", "PIPY", "ZEDS", "XYST", "OGAM", "KNAR", "KNUR" }; // apologies for the Bowdlerization of maybe half a dozen words - the word // list came from scratch.mit.edu which has strict rules about inappropriate // language for young children. uint16_t recorded_word[12]; // record the number of the word for each guess. int recorded_score[12]; // if we can spare the space, use this for verifying scoring. const char const *prompt[12] IN_ROM = { "Your first guess: ", "Your second guess: ", "Your third guess: ", "Your fourth guess: ", "Your fifth guess: ", "Your sixth guess: ", "Your seventh guess: ", "Your eighth guess: ", "Your ninth guess: ", "Your tenth guess: ", "Your penultimate guess: ", "Your final guess: ", }; #ifndef TRUE #define TRUE (0==0) #define FALSE (0!=0) #endif #ifndef CLI unsigned int _x; unsigned int _a; unsigned int _b; unsigned int _c; void initRandom (unsigned int s1, unsigned int s2, unsigned int s3, unsigned int x0) { _x = x0; _a = s1; _b = s2; _c = s3; _x++; _a = (_a ^ _c ^ _x); _b = (_b + _a); _c = ((_c + (_b >> 1)) ^ _a); } uint16_t random8 () { _x++; _a = (_a ^ _c ^ _x); _b = (_b + _a); _c = ((_c + (_b >> 1)) ^ _a); return (uint16_t) _c; } uint16_t random (void) { return (random8 () << 8 | random8 ()) ^ (random8 () << 4); } static inline int isalpha (int c) { return ((('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z'))); } static inline int isupper (int c) { return (('A' <= c) && (c <= 'Z')); } static inline int islower (int c) { return (('a' <= c) && (c <= 'z')); } static inline int tolower (int c) { return c - 'A' + 'a'; } #endif // Variables extracted from main() uint16_t w, temp, p, words = WORDS; // sizeof(word)/sizeof(word[0]); int bulls, cows, guesses, humans_score, turn; char *saved_word; char guess[5]; // needs to be writable static int score (const char *hidden_word, const char *guess, int *bulls, int *cows) { char my_word[5], my_guess[5]; int p; for (p = 0; p < 4; p++) { // make writable my_word[p] = hidden_word[p]; my_guess[p] = guess[p]; } *bulls = 0; *cows = 0; for (p = 0; p < 4; p++) { if (my_guess[p] == my_word[p]) { // remove from further consideration: my_word[p] = ' '; my_guess[p] = '_'; *bulls += 1; } } if ((my_guess[0] != '_') && (my_guess[0] == my_word[p = 1] || my_guess[0] == my_word[p = 2] || my_guess[0] == my_word[p = 3])) { my_word[p] = ' '; *cows += 1; } if ((my_guess[1] != '_') && (my_guess[1] == my_word[p = 0] || my_guess[1] == my_word[p = 2] || my_guess[1] == my_word[p = 3])) { my_word[p] = ' '; *cows += 1; } if ((my_guess[2] != '_') && (my_guess[2] == my_word[p = 0] || my_guess[2] == my_word[p = 1] || my_guess[2] == my_word[p = 3])) { my_word[p] = ' '; *cows += 1; } if ((my_guess[3] != '_') && (my_guess[3] == my_word[p = 0] || my_guess[3] == my_word[p = 1] || my_guess[3] == my_word[p = 2])) { my_word[p] = ' '; *cows += 1; } return *bulls * 5 + *cows; } static void eliminate (uint16_t word_index) { // use a bit array to keep trackl of eliminated words. uint16_t index; int bit; index = word_index >> 3; bit = 1 << (word_index & 7); // assuming 1<<0 == 1 is implemented correctly. eliminated[index] |= bit; } static int is_eliminated (uint16_t word_index) { uint16_t index; int bit; index = word_index >> 3; bit = 1 << (word_index & 7); return (eliminated[index] & bit) != 0; } void dump_marks (int guesses) { int i; #ifdef CLI fprintf (stderr, "You can check the scoring here.\n\n Word Score\n"); #endif for (i = 0; i < guesses; i++) { int bulls, cows, score; uint16_t w; w = recorded_word[i]; score = recorded_score[i]; cows = score % 5; bulls = score / 5; #ifdef CLI fprintf (stderr, "%2d: %s ", i + 1, word[w]); while (bulls-- > 0) fprintf (stderr, "+"); while (cows-- > 0) fprintf (stderr, "?"); fprintf (stderr, "\n"); #endif } #ifdef CLI fprintf (stderr, "\n"); #endif } void check_scores (const char *hidden_word, int guesses) { int i; #ifdef CLI fprintf (stderr, " Score Actual\n"); fprintf (stderr, " Word By You Score\n"); #endif for (i = 0; i < guesses; i++) { int chars, bulls, cows, my_score, your_score; uint16_t w; w = recorded_word[i]; your_score = recorded_score[i]; cows = your_score % 5; bulls = your_score / 5; chars = 4 - (bulls + cows); #ifdef CLI fprintf (stderr, "%2d: %s ", i + 1, word[w]); while (bulls-- > 0) fprintf (stderr, "+"); while (cows-- > 0) fprintf (stderr, "?"); while (chars-- > 0) fprintf (stderr, " "); fprintf (stderr, " "); #endif my_score = score (hidden_word, word[w], &bulls, &cows); chars = 4 - (bulls + cows); #ifdef CLI while (bulls-- > 0) fprintf (stderr, "+"); while (cows-- > 0) fprintf (stderr, "?"); while (chars-- > 0) fprintf (stderr, " "); if (your_score != my_score) fprintf (stderr, " <--- looks like you mis-scored that one..."); fprintf (stderr, "\n"); #endif } #ifdef CLI fprintf (stderr, "\n"); #endif } void ShowGuesses (int guesses, int highlight) { int i, j; char vword[24]; int y = 127 - 28; Wait_Recal (); check_buttons (); // check_joysticks(); Joy_Analog (); Reset0Ref (); Intensity_a (0x50); i = 0; if (guesses) for (;;) { int bulls, cows, score; uint16_t w; w = recorded_word[i]; score = recorded_score[i]; cows = score % 5; bulls = score / 5; for (j = 0; j < 4; j++) vword[j] = word[w][j]; vword[4] = (char) (i == highlight ? '<' : ' '); vword[5] = ' '; vword[6] = ' '; vword[7] = ' '; vword[8] = ' '; vword[9] = ' '; vword[10] = ' '; j = 5; while (bulls-- > 0) vword[j++] = '\x65'; while (cows-- > 0) vword[j++] = '\x64'; if ((i + 6) < guesses) { vword[9] = ' '; w = recorded_word[i + 6]; score = recorded_score[i + 6]; cows = score % 5; bulls = score / 5; for (j = 0; j < 4; j++) vword[10 + j] = word[w][j]; vword[10 + 4] = (char) (i + 6 == highlight ? '<' : ' '); vword[10 + 5] = ' '; vword[10 + 6] = ' '; vword[10 + 7] = ' '; vword[10 + 8] = ' '; vword[10 + 9] = '\x80'; vword[10 + 10] = '\0'; j = 15; while (bulls-- > 0) vword[j++] = '\x65'; while (cows-- > 0) vword[j++] = '\x64'; } else { vword[9] = '\x80'; vword[10] = '\0'; } Print_Str_d (y, -110, vword); // "HELL \x65\x64\x64\x80" y = y - 18; i += 1; if ((i >= guesses) || (i >= 6)) break; } // remove hint when too much text on screen and would flicker... // Would be nice to fade this out when guesses == 6 ... if (guesses < 6) Print_Str_d (127 - 6, -110, "WORD BULL=\x65 COW=\x64\x80"); // Redraw time only verges on unacceptable when number of guesses is high. } #define OK 0 #define NONE 127 #define STATE_GET_HUMANS_GUESS 1 #define STATE_SHOW_COMPUTERS_WORD 2 #define ACTION_HUMAN_QUIT 1 int IO (int STATE) { switch (STATE) { case STATE_GET_HUMANS_GUESS: // Let player enter a word at next slot in ladder. // Don't allow any bad characters { unsigned int i; guesses = 0; i = 0; for (;;) { char *humans_guess; ShowGuesses (guesses, NONE); humans_guess = get_word(-60); if (humans_guess) { Print_Str_d (-120, -100, "YOUR GUESS: \x80"); Print_Str_d (-120, 40, humans_guess); } i += 1; if (i == 100) { i = 0; guesses += 1; } if (guesses == 13) guesses -= 1; } } // if the human quits, return ACTION_HUMAN_QUIT // however at the moment there is nothing in the GUI that would let them quit. return OK; break; case STATE_SHOW_COMPUTERS_WORD: // The human gave up. Show them what the word was for a few seconds, then return. return OK; default: ; } return OK; // actually, not OK but we'll worry about that later. } #define COMPUTER 0 #define HUMAN 1 int main (void) { int i = 1; for (guesses = 0; guesses < 12; guesses++) { recorded_word[guesses] = (unsigned long) guesses *2L; recorded_score[guesses] = i; i++; if (i == 9) i = 10; if (i == 13) i = 20; } guesses = 12; #ifdef DEBUGGING_SCORES humans_score = score ("wasp", "pall", &bulls, &cows); fprintf (stderr, "score(wasp, pall) = %d, bulls = %d, cows = %d\n", humans_score, bulls, cows); exit (0); #endif // fprintf(stderr, "%d words from %s to %s\n", words, word[0], word[words-1]); turn = HUMAN; #ifdef CLI fprintf (stderr, "\nI'll pick a word first, it'll give you a chance to learn the scoring system\n" "before you have to score my guesses...\n\nIMPORTANT NOTE TO REMEMBER: All words have 4 letters.\n\n"); #endif restart: turn = (HUMAN + COMPUTER) - turn; if (turn == HUMAN) { int valid = 0, awarded_score; char *computers_guess; for (w = 0; w < 2564 / 8 + 1; w++) eliminated[w] = 0; #ifdef CLI fprintf (stderr, "I want you to think of a word with FOUR LETTERS and I'll try to\n" "guess it. For every letter in your word that matches a letter in the\n" "same place in my word, you award me a '+'. For each of the remaining\n" "letters in your word, if they appear anywhere in my word, You\n" "give me a '?'.\n\n"); #endif // srandom((unsigned int)clock()); computers_guess = (char *) word[temp = random () % /* words */ SIMPLE_WORDS]; // INIT!!! (human supplies the word, computer guesses...) guesses = 0; #ifdef CLI fprintf (stderr, "My first guess is: %s\n\n(use '+' and '?', or '0' if none.)\n", computers_guess); #endif recorded_word[guesses] = temp; guesses += 1; next_try: #ifdef CLI fprintf (stderr, "What's my score?: "); #endif valid = FALSE; bulls = 0; cows = 0; for (;;) { int c = '\n'; #ifdef CLI c = fgetc (stdin); #endif if (c == EOF) { #ifdef CLI fprintf (stderr, "You give up? OK, I win. Your turn to guess next.\n"); #endif dump_marks (guesses); goto restart; } if (c == '+' || c == '?' || c == '0') valid = valid | TRUE; if (c == '+') bulls += 1; if (c == '?') cows += 1; if (c == '\n') { if (!valid) { #ifdef CLI fprintf (stderr, "Remember, for every letter in your word that matches a letter in the\n" "same place in my word, you award me a '+'. For each of the remaining\n" "letters in your word, if they appear anywhere in my word, You\n" "give me a '?'. Enter '0' if I didn't guess any letters correct at all.\n\n" "What's my score?: "); #endif continue; } else break; } } awarded_score = bulls * 5 + cows; recorded_score[guesses - 1] = awarded_score; if (bulls == 4) { #ifdef CLI fprintf (stderr, "Woo hoo! I won, in %d guesses!\n\n", guesses); #endif dump_marks (guesses); // goto restart; } if (guesses == 12) { #ifdef CLI fprintf (stderr, "Well, that was 12 guesses and I didn't get it.\n"); #endif retype_humans_secret_word: for (;;) { #ifdef CLI fprintf (stderr, "What was your word?\n"); #endif p = 0; for (;;) { int c = '\n'; #ifdef CLI c = fgetc (stdin); #endif if (c == EOF) { #ifdef CLI fprintf (stderr, "\nYou quit? OK.\n"); #endif dump_marks (guesses); // goto restart; } if (isalpha (c)) { if (isupper (c)) c = tolower (c); if (p < 4) { guess[p++] = (char) c; } else { p = 5; // signal to '\n' code that the word was too long } } else if (c == '\n') { if (p != 4) { #ifdef CLI fprintf (stderr, "Your word had to be a word of four letters. Try again.\n"); #endif goto retype_humans_secret_word; } break; } else { // silently ignore bad character #ifdef DEBUG fprintf (stderr, "\nbad character '%c'\n", c); #endif } } // was it a valid word? for (w = 0; w < words; w++) { for (p = 0; p < 4; p++) { if (guess[p] != word[w][p]) break; if (p == 3) goto was_valid; } } #ifdef CLI fprintf (stderr, "There's the problem... \"%s\" was not a word you could use. You lose.\n", guess); #endif was_valid: #ifdef CLI fprintf (stderr, "I think there may have been a scoring error. Let's check:\n\n"); #endif check_scores (guess, guesses); goto restart; } dump_marks (guesses); // goto restart; } #ifdef CLI fprintf (stderr, "OK, so I scored %d bulls and %d cows.\n", bulls, cows); #endif for (w = 0; w < words; w++) { int xbulls, xcows; // check // assume the hidden word was word[i]. // If it were, is the score the player awarded for my guess compatible with that word? int test_score = score (word[w], computers_guess, &xbulls, &xcows); if (test_score != awarded_score) eliminate (w); // when you are down to 3 bulls, and there are multiple choices left for the last letter, // human players usually do something smarter than try them all one by one. } temp = 0; for (w = 0; w < words; w++) { if (!is_eliminated (w)) { temp += 1; #ifdef DEBUG fprintf (stderr, "%s ", word[w]); if ((temp & 7) == 7) fprintf (stderr, "\n"); #endif } } #ifdef CLI fprintf (stderr, "\n"); #endif if (temp == 0) { #ifdef CLI fprintf (stderr, "OK, I'm out of ideas.\n" "I'm pretty sure that either you're using a word I don't know,\n" "or you mis-calculated one of the scores you awarded me earlier.\n"); #endif re_enter_humans_secret_word: for (;;) { #ifdef CLI fprintf (stderr, "What was your word?\n"); #endif p = 0; for (;;) { int c = '\n'; #ifdef CLI c = fgetc (stdin); #endif if (c == EOF) { #ifdef CLI fprintf (stderr, "\nYou quit? OK.\n"); #endif dump_marks (guesses); // goto restart; } if (isalpha (c)) { if (isupper (c)) c = tolower (c); if (p < 4) { guess[p++] = (char) c; } else { p = 5; // signal to (c == '\n') code that the word was too long } } else if (c == '\n') { if (p != 4) { #ifdef CLI fprintf (stderr, "Your word has to be a word of four letters. Try again.\n"); #endif goto re_enter_humans_secret_word; } break; } else { // silently ignore bad character #ifdef DEBUG fprintf (stderr, "\nbad character '%c'\n", c); #endif } } // was it a valid word? for (w = 0; w < words; w++) { for (p = 0; p < 4; p++) { if (guess[p] != word[w][p]) break; if (p == 3) goto was_indeed_valid; } } #ifdef CLI fprintf (stderr, "There's the problem... \"%s\" was not a word you could use. You lose.\n", guess); #endif goto restart; was_indeed_valid: #ifdef CLI fprintf (stderr, "I think there may have been a scoring error. Let's check:\n\n"); #endif check_scores (guess, guesses); goto restart; } } else if (temp == 1) { #ifdef CLI fprintf (stderr, "I think I've guessed it!\n\n"); #endif } else { #ifdef DEBUG fprintf (stderr, "There are %d possible words this could be!\n\n", temp); #endif } // find non-eliminated word 'temp'... temp = random () % temp; // eg random(4) is 0..3 computers_guess = "zzzz"; // delete when sure OK for (w = 0; w < words; w++) { if (!is_eliminated (w)) { if (temp == 0) { computers_guess = (char *) word[temp = w]; break; } temp -= 1; } } bulls = 0; cows = 0; #ifdef CLI fprintf (stderr, "My next guess is: %s\n\n(use '+' and '?', or '0' if none.)\n", computers_guess); #endif recorded_word[guesses] = temp; guesses += 1; goto next_try; } // INIT!!!! (computer supplies the word, human guesses...) guesses = 0; #ifdef CLI fprintf (stderr, "I'm thinking of a word. You can offer valid words as guesses.\n" "For every letter in your word that matches a letter in the same\n" "place in my word, I'll award you a '+'. For each of the remaining\n" "letters in your word, if they appear anywhere in my word I'll\n" "give you a '?'.\n"); #endif // srandom((unsigned int)clock()); saved_word = (char *) word[temp = random () % /* words */ SIMPLE_WORDS]; // fprintf(stderr, "Saved word set to word %d: %s\n", temp, saved_word); #ifdef CLI retype_humans_guess: #endif guess[4] = '\0'; for (;;) { p = 0; bulls = 0; cows = 0; #ifdef CLI fprintf (stderr, "%s", prompt[guesses]); #endif #ifndef CLI if (IO (STATE_GET_HUMANS_GUESS) == ACTION_HUMAN_QUIT) { IO (STATE_SHOW_COMPUTERS_WORD); goto restart; } #else for (;;) { int c = '\n'; #ifdef CLI c = fgetc (stdin); #endif if (c == EOF) { #ifdef CLI fprintf (stderr, "\nYou quit? The word was \"%s\"\n", saved_word); #endif dump_marks (guesses); // goto restart; } if (isalpha (c)) { if (isupper (c)) c = tolower (c); if (p < 4) { guess[p++] = (char) c; } else { p = 5; // signal to '\n' code that the word was too long } } else if (c == '\n') { if (p != 4) { fprintf (stderr, "Your guess has to be a word of four letters. Try again.\n"); goto retype_humans_guess; } break; } else { // silently ignore bad character #ifdef DEBUG fprintf (stderr, "\nbad character '%c'\n", c); #endif } } #endif for (w = 0; w < words; w++) { for (p = 0; p < 4; p++) { if (guess[p] != word[w][p]) break; if (p == 3) goto valid; } } #ifdef CLI fprintf (stderr, "Sorry, \"%s\" is not a word you can use. Try another one.\n", guess); #endif continue; valid: #ifdef CLI fprintf (stderr, "%s: ", guess); #endif humans_score = score (saved_word, guess, &bulls, &cows); recorded_word[guesses] = w; recorded_score[guesses] = humans_score; guesses += 1; #ifdef CLI for (p = 0; p < bulls; p++) fprintf (stderr, "+"); for (p = 0; p < cows; p++) fprintf (stderr, "?"); if (humans_score == 0) fprintf (stderr, "Washout! Zip! Nada!"); fprintf (stderr, "\n"); #endif if (bulls == 4) { #ifdef CLI fprintf (stderr, "You win!\n"); #endif dump_marks (guesses); // goto restart; } if (guesses == 12) { #ifdef CLI fprintf (stderr, "That's your last guess. I win. My word was '%s'\n", saved_word); #endif dump_marks (guesses); goto restart; } } return 0; }