diff -u -N -X files.exc nethack-3.4.3-orig/src/objects.c nethack-3.4.3-alchemy/src/objects.c --- nethack-3.4.3-orig/src/objects.c Sun Dec 07 16:39:14 2003 +++ nethack-3.4.3-alchemy/src/objects.c Thu Dec 11 09:25:51 2003 @@ -729,11 +729,11 @@ POTION("blindness", "yellow", 1, BLINDED, 40, 150, CLR_YELLOW), POTION("paralysis", "emerald", 1, 0, 42, 300, CLR_BRIGHT_GREEN), POTION("speed", "dark green", 1, FAST, 42, 200, CLR_GREEN), -POTION("levitation", "cyan", 1, LEVITATION, 42, 200, CLR_CYAN), +POTION("levitation", "viscous", 1, LEVITATION, 42, 200, CLR_GRAY), POTION("hallucination", "sky blue", 1, HALLUC, 40, 100, CLR_CYAN), POTION("invisibility", "brilliant blue",1, INVIS, 40, 150, CLR_BRIGHT_BLUE), POTION("see invisible", "magenta", 1, SEE_INVIS, 42, 50, CLR_MAGENTA), -POTION("healing", "purple-red", 1, 0, 57, 100, CLR_MAGENTA), +POTION("healing", "amber", 1, 0, 57, 100, CLR_ORANGE), POTION("extra healing", "puce", 1, 0, 47, 100, CLR_RED), POTION("gain level", "milky", 1, 0, 20, 300, CLR_WHITE), POTION("enlightenment", "swirly", 1, 0, 20, 200, CLR_BROWN), diff -u -N -X files.exc nethack-3.4.3-orig/src/potion.c nethack-3.4.3-alchemy/src/potion.c --- nethack-3.4.3-orig/src/potion.c Sun Dec 07 16:39:14 2003 +++ nethack-3.4.3-alchemy/src/potion.c Thu Dec 11 09:25:51 2003 @@ -13,6 +13,7 @@ STATIC_DCL long FDECL(itimeout, (long)); STATIC_DCL long FDECL(itimeout_incr, (long,int)); STATIC_DCL void NDECL(ghost_from_bottle); +STATIC_OVL void NDECL(alchemy_init); STATIC_DCL short FDECL(mixtype, (struct obj *,struct obj *)); /* force `val' to be within valid range for intrinsic timeout value */ @@ -1318,99 +1319,177 @@ } } +/* new alchemy scheme based on color mixing + * YANI by Graham Cox + * Implemented by Nephi Allred on 15 Apr 2003 + * + * Alchemical tables are based on 4 bits describing dark/light level, yellow, blue and red + * + * DYBR + * 0000 white + * 0001 pink + * 0010 sky-blue + * 0011 puce + * 0100 yellow + * 0101 orange + * 0110 emerald + * 0111 brown + * 1000 black + * 1001 ruby + * 1010 brilliant blue + * 1011 magenta + * 1100 golden + * 1101 amber + * 1110 dark green + * 1111 brown + */ + +/* Assumes gain ability is first potion and water is last */ +char alchemy_table1[POT_WATER - POT_GAIN_ABILITY]; +short alchemy_table2[17]; + +#define ALCHEMY_WHITE 0 +#define ALCHEMY_BLACK 8 +#define ALCHEMY_GRAY (alchemy_table2[16]) +#define IS_PRIMARY_COLOR(x) (((x)&7)==1 || ((x)&7)==2 || ((x)&7)==4) +#define IS_SECONDARY_COLOR(x) (((x)&7)==3 || ((x)&7)==5 || ((x)&7)==6) +#define IS_LIGHT_COLOR(x) (((x)&8)==0) +#define IS_DARK_COLOR(x) ((x)&8) + +/* do a one-time set up of alchemical tables */ +STATIC_OVL void +alchemy_init() +{ + static boolean init = FALSE; + + if(init==FALSE) { + short i; + const char* potion_desc; + + for(i=POT_GAIN_ABILITY;i<=POT_WATER;i++) { + potion_desc = OBJ_DESCR(objects[i]); + if(0==strcmp(potion_desc,"white")) { + alchemy_table1[i-POT_GAIN_ABILITY]=0; + alchemy_table2[0]=i; + } else if (0==strcmp(potion_desc,"pink")) { + alchemy_table1[i-POT_GAIN_ABILITY]=1; + alchemy_table2[1]=i; + } else if (0==strcmp(potion_desc,"sky blue")) { + alchemy_table1[i-POT_GAIN_ABILITY]=2; + alchemy_table2[2]=i; + } else if (0==strcmp(potion_desc,"puce")) { + alchemy_table1[i-POT_GAIN_ABILITY]=3; + alchemy_table2[3]=i; + } else if (0==strcmp(potion_desc,"yellow")) { + alchemy_table1[i-POT_GAIN_ABILITY]=4; + alchemy_table2[4]=i; + } else if (0==strcmp(potion_desc,"orange")) { + alchemy_table1[i-POT_GAIN_ABILITY]=5; + alchemy_table2[5]=i; + } else if (0==strcmp(potion_desc,"emerald")) { + alchemy_table1[i-POT_GAIN_ABILITY]=6; + alchemy_table2[6]=i; + } else if (0==strcmp(potion_desc,"brown")) { + alchemy_table1[i-POT_GAIN_ABILITY]=7; + alchemy_table2[7]=i; + alchemy_table2[15]=i; + } else if (0==strcmp(potion_desc,"black")) { + alchemy_table1[i-POT_GAIN_ABILITY]=8; + alchemy_table2[8]=i; + } else if (0==strcmp(potion_desc,"ruby")) { + alchemy_table1[i-POT_GAIN_ABILITY]=9; + alchemy_table2[9]=i; + } else if (0==strcmp(potion_desc,"brilliant blue")) { + alchemy_table1[i-POT_GAIN_ABILITY]=10; + alchemy_table2[10]=i; + } else if (0==strcmp(potion_desc,"magenta")) { + alchemy_table1[i-POT_GAIN_ABILITY]=11; + alchemy_table2[11]=i; + } else if (0==strcmp(potion_desc,"golden")) { + alchemy_table1[i-POT_GAIN_ABILITY]=12; + alchemy_table2[12]=i; + } else if (0==strcmp(potion_desc,"amber")) { + alchemy_table1[i-POT_GAIN_ABILITY]=13; + alchemy_table2[13]=i; + } else if (0==strcmp(potion_desc,"dark green")) { + alchemy_table1[i-POT_GAIN_ABILITY]=14; + alchemy_table2[14]=i; + } else if (0==strcmp(potion_desc,"cloudy")) { + alchemy_table1[i-POT_GAIN_ABILITY]=-1; + alchemy_table2[16]=i; + } else { + alchemy_table1[i-POT_GAIN_ABILITY]=-1; + } + } + init = TRUE; + } +} + STATIC_OVL short mixtype(o1, o2) register struct obj *o1, *o2; /* returns the potion type when o1 is dipped in o2 */ { - /* cut down on the number of cases below */ - if (o1->oclass == POTION_CLASS && - (o2->otyp == POT_GAIN_LEVEL || - o2->otyp == POT_GAIN_ENERGY || - o2->otyp == POT_HEALING || - o2->otyp == POT_EXTRA_HEALING || - o2->otyp == POT_FULL_HEALING || - o2->otyp == POT_ENLIGHTENMENT || - o2->otyp == POT_FRUIT_JUICE)) { - struct obj *swp; - - swp = o1; o1 = o2; o2 = swp; - } - - switch (o1->otyp) { - case POT_HEALING: - switch (o2->otyp) { - case POT_SPEED: - case POT_GAIN_LEVEL: - case POT_GAIN_ENERGY: - return POT_EXTRA_HEALING; - } - case POT_EXTRA_HEALING: - switch (o2->otyp) { - case POT_GAIN_LEVEL: - case POT_GAIN_ENERGY: - return POT_FULL_HEALING; - } - case POT_FULL_HEALING: - switch (o2->otyp) { - case POT_GAIN_LEVEL: - case POT_GAIN_ENERGY: - return POT_GAIN_ABILITY; - } - case UNICORN_HORN: - switch (o2->otyp) { - case POT_SICKNESS: - return POT_FRUIT_JUICE; - case POT_HALLUCINATION: - case POT_BLINDNESS: - case POT_CONFUSION: - return POT_WATER; - } - break; - case AMETHYST: /* "a-methyst" == "not intoxicated" */ - if (o2->otyp == POT_BOOZE) - return POT_FRUIT_JUICE; - break; - case POT_GAIN_LEVEL: - case POT_GAIN_ENERGY: - switch (o2->otyp) { - case POT_CONFUSION: - return (rn2(3) ? POT_BOOZE : POT_ENLIGHTENMENT); - case POT_HEALING: - return POT_EXTRA_HEALING; - case POT_EXTRA_HEALING: - return POT_FULL_HEALING; - case POT_FULL_HEALING: - return POT_GAIN_ABILITY; - case POT_FRUIT_JUICE: - return POT_SEE_INVISIBLE; - case POT_BOOZE: - return POT_HALLUCINATION; - } - break; - case POT_FRUIT_JUICE: - switch (o2->otyp) { - case POT_SICKNESS: - return POT_SICKNESS; - case POT_SPEED: - return POT_BOOZE; - case POT_GAIN_LEVEL: - case POT_GAIN_ENERGY: - return POT_SEE_INVISIBLE; - } - break; - case POT_ENLIGHTENMENT: - switch (o2->otyp) { - case POT_LEVITATION: - if (rn2(3)) return POT_GAIN_LEVEL; + if(o1->oclass == POTION_CLASS) { + char i1,i2,result; + + alchemy_init(); + i1 = alchemy_table1[o1->otyp-POT_GAIN_ABILITY]; + i2 = alchemy_table1[o2->otyp-POT_GAIN_ABILITY]; + + /* check that both potions are of mixable types */ + if(i1<0 || i2<0) + return 0; + + /* swap for simplified checks */ + if(i2==ALCHEMY_WHITE || (i2==ALCHEMY_BLACK && i1!=ALCHEMY_WHITE)) { + result = i1; + i1 = i2; + i2 = result; + } + + if(i1==ALCHEMY_WHITE && i2==ALCHEMY_BLACK) { + return ALCHEMY_GRAY; + } else if( (IS_PRIMARY_COLOR(i1) && IS_PRIMARY_COLOR(i2)) + || (IS_SECONDARY_COLOR(i1) && IS_SECONDARY_COLOR(i2)) ) { + /* bitwise OR simulates pigment addition */ + result = i1 | i2; + /* adjust light/dark level if necessary */ + if((i1^i2)&8) { + if(o1->odiluted==o2->odiluted) { + /* same dilution level, randomly toggle */ + result ^= (rn2(2)<<3); + } else { + /* use dark/light level of undiluted potion */ + result ^= (o1->odiluted ? i1:i2)&8; + } + } + } else if ( (i1==ALCHEMY_WHITE && IS_DARK_COLOR(i2)) + || (i1==ALCHEMY_BLACK && IS_LIGHT_COLOR(i2))) { + /* toggle light/dark bit */ + result = i2 ^ 8; + } else { + return 0; + } + return alchemy_table2[result]; + } else { + switch (o1->otyp) { + case UNICORN_HORN: + switch (o2->otyp) { + case POT_SICKNESS: + return POT_FRUIT_JUICE; + case POT_HALLUCINATION: + case POT_BLINDNESS: + case POT_CONFUSION: + return POT_WATER; + } + break; + case AMETHYST: /* "a-methyst" == "not intoxicated" */ + if (o2->otyp == POT_BOOZE) + return POT_FRUIT_JUICE; break; - case POT_FRUIT_JUICE: - return POT_BOOZE; - case POT_BOOZE: - return POT_CONFUSION; - } - break; - } + } + } return 0; } @@ -1664,7 +1743,13 @@ return(1); } else if(obj->oclass == POTION_CLASS && obj->otyp != potion->otyp) { /* Mixing potions is dangerous... */ - pline_The("potions mix..."); + /* Give a clue to what's going on ... */ + if(potion->dknown && obj->dknown) { + You("mix the %s potion with the %s one ...", + OBJ_DESCR(objects[potion->otyp]), + OBJ_DESCR(objects[obj->otyp])); + } else + pline_The("potions mix..."); /* KMH, balance patch -- acid is particularly unstable */ if (obj->cursed || obj->otyp == POT_ACID || !rn2(10)) { pline("BOOM! They explode!");