//#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;
}