Clarent is the sword which Arthur drew forth from the stone, proving himself a rightful king. It represents authority and leadership. Clarent cleaves through stone easily, but only those dedicated to law can remove it from a stony grasp. Clarent has the following properties: - Intelligent lawful short sword - Can be used to dig - When invoked, reveals the location of your retinue (all tame creatures) on the level, and increases the tameness of any within line of sight - Acts as a luckstone - Clarent submits to being held second to Excalibur (but not the other way around) - Annoys demons - If Clarent is stuck in a wall/door/tree/stone, then it can be pulled out by #untrap as long as you are at least devoutly lawful - Is not generated at random. - +d8+2 to hit and +d2 damage against thick-skinned monsters (all gargoyles, all mimics, all naga, all baby naga, all dragons, all baby dragons, the Chromatic Dragon, Ixoth, {gold, wood, clay, stone, glass, iron} golems, mumakil, titanotheres, baluchitheria, mastodons, earth elementals, xorn, skeletons, horned devils, barbed devils, sharks, crocodiles, salamanders) Excalibur's demon-annoying properties have been transferred to Clarent. Clarent is now the Lawful crowning gift. If you are wielding a non-artifact short sword when crowned, it will be transformed into Clarent, much as used to happen for Excalibur. Otherwise, assuming Clarent doesn't already exist in the game, it will appear. If you are beside a wall/door/tree/stone when you receive Clarent from crowning or from a wish, it will arrive stuck into the stone; you must then be at least devoutly lawful to pull it out (by #untrap), as discussed above. diff -Nurd nethack/dat/data.base nethack-clarent/dat/data.base --- nethack/dat/data.base 2006-04-06 21:04:27.000000000 +0100 +++ nethack-clarent/dat/data.base 2007-03-07 19:01:03.000000000 +0000 @@ -669,6 +669,12 @@ tiamat Tiamat is said to be the mother of evil dragonkind. She is extremely vain. +clarent + Clarent is the sword which Arthur drew forth from the stone, + proving himself a rightful king. It represents authority + and leadership. Clarent cleaves through stone easily, but + only those dedicated to law can remove it from a stony + grasp. ~elven cloak ~oilskin cloak *cloak* diff -Nurd nethack/include/artifact.h nethack-clarent/include/artifact.h --- nethack/include/artifact.h 2006-04-06 21:04:27.000000000 +0100 +++ nethack-clarent/include/artifact.h 2007-03-06 20:22:46.000000000 +0000 @@ -34,6 +34,7 @@ #define SPFX_DBONUS 0x1F00000L /* attack bonus mask */ #define SPFX_XRAY 0x2000000L /* gives X-RAY vision to player */ #define SPFX_REFLECT 0x4000000L /* Reflection */ +#define SPFX_DIG 0x8000000L /* Can dig with artifact, as if it were a pick */ struct artifact { @@ -60,5 +61,6 @@ #define CREATE_PORTAL (LAST_PROP+7) #define ENLIGHTENING (LAST_PROP+8) #define CREATE_AMMO (LAST_PROP+9) +#define LEADERSHIP (LAST_PROP+10) #endif /* ARTIFACT_H */ diff -Nurd nethack/include/artilist.h nethack-clarent/include/artilist.h --- nethack/include/artilist.h 2006-04-06 21:04:27.000000000 +0100 +++ nethack-clarent/include/artilist.h 2007-03-06 23:26:29.000000000 +0000 @@ -231,6 +231,14 @@ NO_ATTK, NO_DFNS, CARY(AD_MAGM), CREATE_PORTAL, A_NEUTRAL, PM_WIZARD, NON_PM, 4000L ), +/* Note that Clarent's SPFX_DIG gives it another +2 to hit against thick-skinned + monsters, as well as against wall-passers. Another special effect of Clarent + is that it can be pulled out of a wall it is stuck in (by #untrapping towards + it) if you are devoutly lawful. */ +A("Clarent", SHORT_SWORD, + (SPFX_NOGEN|SPFX_RESTR|SPFX_DEFN|SPFX_INTEL|SPFX_LUCK|SPFX_DIG|SPFX_DFLAG1), 0, M1_THICK_HIDE, + PHYS(8,2), NO_DFNS, NO_CARY, + LEADERSHIP, A_LAWFUL, PM_KNIGHT, NON_PM, 4000L ), /* * terminator; otyp must be zero */ diff -Nurd nethack/include/extern.h nethack-clarent/include/extern.h --- nethack/include/extern.h 2006-04-06 21:04:27.000000000 +0100 +++ nethack-clarent/include/extern.h 2007-03-07 14:18:11.000000000 +0000 @@ -62,6 +62,7 @@ E int NDECL(nartifact_exist); E boolean FDECL(spec_ability, (struct obj *,unsigned long)); E boolean FDECL(confers_luck, (struct obj *)); +E boolean FDECL(arti_digs, (struct obj *)); E boolean FDECL(arti_reflects, (struct obj *)); E boolean FDECL(restrict_name, (struct obj *,const char *)); E boolean FDECL(defends, (int,struct obj *)); @@ -205,6 +206,7 @@ E int FDECL(food_detect, (struct obj *)); E int FDECL(object_detect, (struct obj *,int)); E int FDECL(monster_detect, (struct obj *,int)); +E int FDECL(pet_detect_and_tame, (struct obj *)); E int FDECL(trap_detect, (struct obj *)); E const char *FDECL(level_distance, (d_level *)); E void FDECL(use_crystal_ball, (struct obj *)); diff -Nurd nethack/include/obj.h nethack-clarent/include/obj.h --- nethack/include/obj.h 2006-04-06 21:04:27.000000000 +0100 +++ nethack-clarent/include/obj.h 2007-03-06 21:50:23.000000000 +0000 @@ -132,7 +132,8 @@ objects[otmp->otyp].oc_skill == P_AXE) #define is_pick(otmp) ((otmp->oclass == WEAPON_CLASS || \ otmp->oclass == TOOL_CLASS) && \ - objects[otmp->otyp].oc_skill == P_PICK_AXE) + (objects[otmp->otyp].oc_skill == P_PICK_AXE || \ + arti_digs(otmp))) #define is_sword(otmp) (otmp->oclass == WEAPON_CLASS && \ objects[otmp->otyp].oc_skill >= P_SHORT_SWORD && \ objects[otmp->otyp].oc_skill <= P_SABER) diff -Nurd nethack/src/artifact.c nethack-clarent/src/artifact.c --- nethack/src/artifact.c 2006-04-06 21:04:27.000000000 +0100 +++ nethack-clarent/src/artifact.c 2007-03-07 14:17:59.000000000 +0000 @@ -64,8 +64,10 @@ art->alignment = alignmnt; /* Excalibur can be used by any lawful character, not just knights */ - if (!Role_if(PM_KNIGHT)) + if (!Role_if(PM_KNIGHT)) { artilist[ART_EXCALIBUR].role = NON_PM; + artilist[ART_CLARENT].role = NON_PM; + } /* Fix up the quest artifact */ if (urole.questarti) { @@ -262,6 +264,17 @@ return (obj->oartifact && spec_ability(obj, SPFX_LUCK)); } +/* used so that callers don't need to known about SPFX_ codes */ +boolean +arti_digs(obj) +struct obj *obj; +{ + /* might as well check for this too */ + if ((obj->oclass == WEAPON_CLASS || obj->oclass == TOOL_CLASS) && (objects[obj->otyp].oc_skill == P_PICK_AXE)) return TRUE; + + return (obj->oartifact && spec_ability(obj, SPFX_DIG)); +} + /* used to check whether a monster is getting reflection from an artifact */ boolean arti_reflects(obj) @@ -514,7 +527,8 @@ (oart->alignment != u.ualign.type || u.ualign.record < 0); } else if (!is_covetous(mon->data) && !is_mplayer(mon->data)) { badclass = self_willed && - oart->role != NON_PM && oart != &artilist[ART_EXCALIBUR]; + oart->role != NON_PM && !(oart == &artilist[ART_EXCALIBUR] + || oart == &artilist[ART_CLARENT]); badalign = (oart->spfx & SPFX_RESTR) && oart->alignment != A_NONE && (oart->alignment != sgn(mon->data->maligntyp)); } else { /* an M3_WANTSxxx monster or a fake player */ @@ -1216,6 +1230,10 @@ (void) seffects(&pseudo); break; } + case LEADERSHIP: { + (void) pet_detect_and_tame(obj); + break; + } case HEALING: { int healamt = (u.uhpmax + 1 - u.uhp) / 2; long creamed = (long)u.ucreamed; diff -Nurd nethack/src/detect.c nethack-clarent/src/detect.c --- nethack/src/detect.c 2006-04-06 21:04:27.000000000 +0100 +++ nethack-clarent/src/detect.c 2007-03-07 19:28:57.000000000 +0000 @@ -641,6 +641,68 @@ return 0; } +/* + * Used by: LEADERSHIP artifacts (Clarent) + * + * Returns 1 if nothing was detected. + * Returns 0 if something was detected. + */ +int +pet_detect_and_tame(otmp) +register struct obj *otmp; /* detecting object (if any) */ +{ + register struct monst *mtmp; + int mcnt = 0; + + + /* Note: This used to just check fmon for a non-zero value + * but in versions since 3.3.0 fmon can test TRUE due to the + * presence of dmons, so we have to find at least one + * with positive hit-points to know for sure. + */ + for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) + if (!DEADMONSTER(mtmp) && mtmp->mtame) { + mcnt++; + break; + } + + if (!mcnt) { + boolean savebeginner = flags.beginner; /* prevent non-delivery of */ + flags.beginner = FALSE; /* message */ + if (otmp) + strange_feeling((struct obj *)0, Hallucination ? + "You suddenly recall the hamster you had as a child." : + "You feel lonely."); + flags.beginner = savebeginner; + return 1; + } else { + cls(); + display_self(); + for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) { + if (DEADMONSTER(mtmp)) continue; + if (mtmp->mtame && mtmp->mx > 0) { + show_glyph(mtmp->mx,mtmp->my,mon_to_glyph(mtmp)); + /* don't be stingy - display entire worm */ + if (mtmp->data == &mons[PM_LONG_WORM]) detect_wsegs(mtmp,0); + /* increase tameness */ + if(canseemon(mtmp) && mtmp->mtame < 20) mtmp->mtame++; + } + } + You(Hallucination ? + "are at one with your comrades." : + "sense the presence of your retinue."); + for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) { + if (!DEADMONSTER(mtmp) && (mtmp->mtame && mtmp->mx > 0) && canseemon(mtmp)) + pline("%s is in awe of %s!", upstart(y_monnam(mtmp)), yname(otmp)); + } + display_nhwindow(WIN_MAP, TRUE); + docrt(); + if (Underwater) under_water(2); + if (u.uburied) under_ground(2); + } + return 0; +} + STATIC_OVL void sense_trap(trap, x, y, src_cursed) struct trap *trap; diff -Nurd nethack/src/makemon.c nethack-clarent/src/makemon.c --- nethack/src/makemon.c 2006-04-06 21:04:27.000000000 +0100 +++ nethack-clarent/src/makemon.c 2007-03-07 00:08:25.000000000 +0000 @@ -1047,7 +1047,7 @@ if(is_dprince(ptr) && ptr->msound == MS_BRIBE) { mtmp->mpeaceful = mtmp->minvis = mtmp->perminvis = 1; mtmp->mavenge = 0; - if (uwep && uwep->oartifact == ART_EXCALIBUR) + if (uwep && uwep->oartifact == ART_CLARENT) mtmp->mpeaceful = mtmp->mtame = FALSE; } #ifndef DCC30_BUG diff -Nurd nethack/src/minion.c nethack-clarent/src/minion.c --- nethack/src/minion.c 2006-04-06 21:04:27.000000000 +0100 +++ nethack-clarent/src/minion.c 2007-03-07 00:08:37.000000000 +0000 @@ -144,7 +144,7 @@ { long cash, demand, offer; - if (uwep && uwep->oartifact == ART_EXCALIBUR) { + if (uwep && uwep->oartifact == ART_CLARENT) { pline("%s looks very angry.", Amonnam(mtmp)); mtmp->mpeaceful = mtmp->mtame = 0; set_malign(mtmp); diff -Nurd nethack/src/pray.c nethack-clarent/src/pray.c --- nethack/src/pray.c 2006-04-06 21:04:27.000000000 +0100 +++ nethack-clarent/src/pray.c 2007-03-07 18:20:57.000000000 +0000 @@ -656,6 +658,8 @@ switch (u.ualign.type) { case A_LAWFUL: u.uevent.uhand_of_elbereth = 1; + in_hand = (uwep && uwep->oartifact == ART_CLARENT); + already_exists = exist_artifact(SHORT_SWORD, artiname(ART_CLARENT)); verbalize("I crown thee... The Hand of Elbereth!"); break; case A_NEUTRAL: @@ -707,15 +711,39 @@ case A_LAWFUL: if (class_gift != STRANGE_OBJECT) { ; /* already got bonus above */ - } else if (obj && obj->otyp == LONG_SWORD && !obj->oartifact) { + } else if (in_hand) { + if(obj->dknown) + pline("%s rings gently for a moment.", xname(obj)); + else + Your("%s rings gently for a moment.", xname(obj)); + obj->dknown = TRUE; + } else if (obj && obj->otyp == SHORT_SWORD && !obj->oartifact) { if (!Blind) Your("sword shines brightly for a moment."); - obj = oname(obj, artiname(ART_EXCALIBUR)); - if (obj && obj->oartifact == ART_EXCALIBUR) u.ugifts++; + obj = oname(obj, artiname(ART_CLARENT)); + if (obj && obj->oartifact == ART_CLARENT) u.ugifts++; + } else if (!already_exists) { + int x = u.ux; + int y = u.uy; + if(!u.uswallow) { + /* try to find a neighbouring wall to stick it into + (preferably an orthogonally adjacent one), + otherwise on current square */ + if(levl[u.ux-1][u.uy+0].typ <=SCORR) { x += -1; y += 0; } + else if(levl[u.ux+1][u.uy+0].typ <=SCORR) { x += 1; y += 0; } + else if(levl[u.ux+0][u.uy-1].typ <=SCORR) { x += 0; y += -1; } + else if(levl[u.ux+0][u.uy+1].typ <=SCORR) { x += 0; y += 1; } + else if(levl[u.ux-1][u.uy-1].typ <=SCORR) { x += -1; y += -1; } + else if(levl[u.ux-1][u.uy+1].typ <=SCORR) { x += -1; y += 1; } + else if(levl[u.ux+1][u.uy-1].typ <=SCORR) { x += 1; y += -1; } + else if(levl[u.ux+1][u.uy+1].typ <=SCORR) { x += 1; y += 1; } + } + obj = mksobj(SHORT_SWORD, FALSE, FALSE); + obj = oname(obj, artiname(ART_CLARENT)); + obj->spe = 1; + if (!u.uswallow && flooreffects(obj,x,y,"drop")) return; + if(!(x==u.ux && y==u.uy)) { + pline("A sword flashes through the air and embeds itself in %s next to you!", + IS_TREE(levl[x][y].typ) ? "a tree" : + (IS_WALL(levl[x][y].typ) || levl[x][y].typ == SDOOR) ? "the wall" : + closed_door(x,y) ? "a door" : + "the stone"); + place_object(obj, x, y); + stackobj(obj); + if(Blind && Levitation) + map_object(obj, 0); + newsym(x,y); /* remap location */ + } else { + at_your_feet("A sword"); + dropy(obj); + } + u.ugifts++; } - /* acquire Excalibur's skill regardless of weapon or gift */ - unrestrict_weapon_skill(P_LONG_SWORD); - if (obj && obj->oartifact == ART_EXCALIBUR) - discover_artifact(ART_EXCALIBUR); + /* acquire Clarent's skill regardless of weapon or gift */ + unrestrict_weapon_skill(P_SHORT_SWORD); + if (obj && obj->oartifact == ART_CLARENT) + discover_artifact(ART_CLARENT); break; case A_NEUTRAL: if (class_gift != STRANGE_OBJECT) { diff -Nurd nethack/src/trap.c nethack-clarent/src/trap.c --- nethack/src/trap.c 2006-04-06 21:04:27.000000000 +0100 +++ nethack-clarent/src/trap.c 2007-03-07 13:52:35.000000000 +0000 @@ -3418,6 +3418,34 @@ containercnt++; if (containercnt > 1) break; } + if(otmp->oartifact == ART_CLARENT && (levl[x][y].typ <= SCORR)) { + Strcpy(the_trap, doname(otmp)); + + Strcat(the_trap, " here, embedded in "); + if (IS_TREE(levl[x][y].typ)) + Strcat(the_trap, "a tree"); + else if (IS_WALL(levl[x][y].typ) || levl[x][y].typ == SDOOR) + Strcat(the_trap, "a wall"); + else if (closed_door(x,y)) + Strcat(the_trap, "a door"); + else + Strcat(the_trap, "stone"); + + You("see %s.", the_trap); + switch (ynq("Try to pull it out?")) { + case 'q': return(1); + case 'n': trap_skipped = TRUE; continue; + } + + if(touch_artifact(otmp, &youmonst) && u.ualign.type == A_LAWFUL && u.ualign.record >= 14) { + pline("It slides out easily!"); + (void) pick_obj(otmp); + } else { + pline("It is stuck fast!"); + } + + return(1); + } } if ((ttmp = t_at(x,y)) && ttmp->tseen) { diff -Nurd nethack/src/wield.c nethack-clarent/src/wield.c --- nethack/src/wield.c 2006-04-06 21:04:27.000000000 +0100 +++ nethack-clarent/src/wield.c 2007-03-06 22:41:30.000000000 +0000 @@ -490,7 +490,11 @@ pline("%s isn't one-handed.", Yname2(otmp)); } else if (uarms) You_cant("use two weapons while wearing a shield."); - else if (uswapwep->oartifact) + else if (uswapwep->oartifact==ART_CLARENT && uwep->oartifact==ART_EXCALIBUR) { + pline("%s %s to being held second to Excalibur.", + Yname2(uswapwep), otense(uswapwep, "submit")); + return (TRUE); + } else if (uswapwep->oartifact) pline("%s %s being held second to another weapon!", Yname2(uswapwep), otense(uswapwep, "resist")); else if (!uarmg && !Stone_resistance && (uswapwep->otyp == CORPSE && diff -Nurd nethack/src/zap.c nethack-clarent/src/zap.c --- nethack/src/zap.c 2006-04-06 21:04:27.000000000 +0100 +++ nethack-clarent/src/zap.c 2007-03-07 18:41:10.000000000 +0000 @@ -4125,18 +4125,46 @@ if (otmp != &zeroobj) { /* The(aobjnam()) is safe since otmp is unidentified -dlc */ - (void) hold_another_object(otmp, u.uswallow ? - "Oops! %s out of your reach!" : - (Is_airlevel(&u.uz) || - Is_waterlevel(&u.uz) || - levl[u.ux][u.uy].typ < IRONBARS || - levl[u.ux][u.uy].typ >= ICE) ? - "Oops! %s away from you!" : - "Oops! %s to the floor!", - The(aobjnam(otmp, - Is_airlevel(&u.uz) || u.uinwater ? - "slip" : "drop")), - (const char *)0); + int x = u.ux; + int y = u.uy; + if(otmp->oartifact == ART_CLARENT && !u.uswallow) { + /* try to find a neighbouring wall to stick it into + (preferably an orthogonally adjacent one), + otherwise on current square */ + if(levl[x-1][y+0].typ <=SCORR) { x += -1; y += 0; } + else if(levl[x+1][y+0].typ <=SCORR) { x += 1; y += 0; } + else if(levl[x+0][y-1].typ <=SCORR) { x += 0; y += -1; } + else if(levl[x+0][y+1].typ <=SCORR) { x += 0; y += 1; } + else if(levl[x-1][y-1].typ <=SCORR) { x += -1; y += -1; } + else if(levl[x-1][y+1].typ <=SCORR) { x += -1; y += 1; } + else if(levl[x+1][y-1].typ <=SCORR) { x += 1; y += -1; } + else if(levl[x+1][y+1].typ <=SCORR) { x += 1; y += 1; } + } + if(!(x==u.ux && y==u.uy)) { + pline("A sword flashes through the air and embeds itself in %s next to you!", + IS_TREE(levl[x][y].typ) ? "a tree" : + (IS_WALL(levl[x][y].typ) || levl[x][y].typ == SDOOR) ? "the wall" : + closed_door(x,y) ? "a door" : + "the stone"); + place_object(otmp, x, y); + stackobj(otmp); + if(Blind && Levitation) + map_object(otmp, 0); + newsym(x,y); /* remap location */ + } else { + (void) hold_another_object(otmp, u.uswallow ? + "Oops! %s out of your reach!" : + (Is_airlevel(&u.uz) || + Is_waterlevel(&u.uz) || + levl[x][y].typ < IRONBARS || + levl[x][y].typ >= ICE) ? + "Oops! %s away from you!" : + "Oops! %s to the floor!", + The(aobjnam(otmp, + Is_airlevel(&u.uz) || u.uinwater ? + "slip" : "drop")), + (const char *)0); + } u.ublesscnt += rn1(100,50); /* the gods take notice */ } }