Spanish Verb Conjugator
Python, 172 168 743 characters - 1796 bonus = -1053

Updated to take the stem-changing challenge.

p,v=raw_input().split()
y="aee";z=y+'n'
x=["ooo",y+'s',y,y,y,"aeimos","ae\x00is",z,z]["YoTuElEaUdNsVsEsUs".index(p[0]+p[-1])/2]
s=v[:-2]
X=v='eJw1UuHS5CAIe1aqrNsZhR6w/tj5Hv4Sv7uODRYDxEzlylKTplHS3xrS/3yIm4kntCTVSipkazaZ\n+AA32h3tY1ut+VL7NreXxsEEsgSheGynlJv/GNVvsPs9CIl2hoCSV+gYfuH7rdAyIQdr3+x92yCg\n2g7WEp4vMfTKgogyHabbL4z1l1p/1PLBCF4o9AjtmJBc6wpOTJykM+O0Ib2Y+FyCAuv5wcwCd+Ks\n4+XCdSwhqMIf/eJOFPMjV/rc0jw6IEvm8vjKdBuy/JryMPmEXwIiDInhtK01n1iDPrGu6/A5uy4/\nkBVd89R1OjvHCXbSnoDyaB23nhseElHosf45rzYC1zOevyDojQ548fjGCGg8M5aD8EAmB9GqgFHk\nBzRwDwJ6EcgK5aSDZ2/4TSAjKOMXd3gPh6sTq/+GApG0wkSYdzSBz/AXclUQ+g=='.decode('base64').decode('zip')
if s in X:
 j=X.index(s)&lt;326
 s=(s.replace('oe'[j],'ui'[j]+'e'),s)[p[0]in'NV']
print s+x["aei".index(v[-2])]+x[3:]


Usage:

$ echo "Ellas querer" | python conj_golf2.py
quieren


Test on non-stem-changing inputs:

Yo ensenar -&gt; enseno
Yo escribir -&gt; escribo
Tu ensenar -&gt; ensenas
Tu escribir -&gt; escribes
El ensenar -&gt; ensena
El escribir -&gt; escribe
Ella ensenar -&gt; ensena
Ella escribir -&gt; escribe
Usted ensenar -&gt; ensena
Usted escribir -&gt; escribe
Nosotros ensenar -&gt; ensenamos
Nosotros escribir -&gt; escribimos
Vosotros ensenar -&gt; ensenais
Vosotros escribir -&gt; escribis
Ellos ensenar -&gt; ensenan
Ellos escribir -&gt; escriben
Ellas ensenar -&gt; ensenan
Ellas escribir -&gt; escriben
Ustedes ensenar -&gt; ensenan
Ustedes escribir -&gt; escriben


Stem-changing input examples:

It does both e->ie changes and o->ue changes, properly avoiding the nostros + vostros cases:

$ echo "Yo abstenir"|python conj_golf2.py
abstieno
$ echo "Nostros abstenir"|python conj_golf2.py
abstenimos
$ echo "Tu almorzar"|python conj_golf2.py
almuerzas
$ echo "Vostros almorzar"|python conj_golf2.py
almorzais


Here is how the bonus was determined and the data string generated, from which you can deduce the verbs on which it works:

e="absten.acert.adher.adquer.advert.apret.asent.atraves.calent.cerr."+\
  "circunven.comenz.confer.confes.consent.conten.contraven.conven.convert."+\
  "difer.diger.discern.disent.freg.gobern.hed.hel.her.herv.infer.inger."+\
  "invern.invert.malher.manifest.ment.neg.nev.obten.ofend.pens.perd."+\
  "quer.recomend.reg.seg.sembr.sent.serr.sosegsosten.soterr.subarrend."+\
  "suger.tembl.tend.ten.tent.transfer.tropez.ven.vert"

u="absolv.acord.acost.almorz.along.amobl.apost.aprob.asol.avergonz."+\
  "coc.col.colg.cont.cost.degoll.demol.demostr.desaprob.descolg.descontr."+\
  "desos.destorc.devolv.disolv.dol.dorm.encontr.engros.envolv.forz.holg."+\
  "holl.llov.mol.mor.mostr.mov.ol.pobl.prob.record.reforz.remord.remov.renov."+\
  "repobl.resolv.resoll.reson.retorc.revolc.revolv."+\
  "rod.rog.sol.sold.sol.solt.son.torc.tost.tron.vol.volc.volv"

words = e.split(".") + u.split(".")
bonus = 0
for word in words:
    bonus += (len(word)+2)*2
print "Bonus: %d from %d stem-changing verbs" % (bonus, len(words))

s=(e+"|"+u).replace(".","")
zipped = s.encode('zip')
b64 = zipped.encode('base64')
print "The separator is at index %d" % s.index("|")
print "Uncompressed: %d chars, %d repr" % (len(s), len(`s`))
print "Compressed: %d chars, %d repr" % (len(zipped), len(`zipped`))
print "Comp+B64: %d chars, %d repr" % (len(b64), len(`b64`))

print "v="+`b64`


Which gives:

$ python conj_help.py
Bonus: 1796 from 127 stem-changing verbs
The separator is at index 326
Uncompressed: 645 chars, 647 repr
Compressed: 331 chars, 1015 repr
Comp+B64: 450 chars, 458 repr
v='eJw1UuHS5CAIe1aqrNsZhR6w/tj5Hv4Sv7uODRYDxEzlylKTplHS3xrS/3yIm4kntCTVSipkazaZ\n+AA32h3tY1ut+VL7NreXxsEEsgSheGynlJv/GNVvsPs9CIl2hoCSV+gYfuH7rdAyIQdr3+x92yCg\n2g7WEp4vMfTKgogyHabbL4z1l1p/1PLBCF4o9AjtmJBc6wpOTJykM+O0Ib2Y+FyCAuv5wcwCd+Ks\n4+XCdSwhqMIf/eJOFPMjV/rc0jw6IEvm8vjKdBuy/JryMPmEXwIiDInhtK01n1iDPrGu6/A5uy4/\nkBVd89R1OjvHCXbSnoDyaB23nhseElHosf45rzYC1zOevyDojQ548fjGCGg8M5aD8EAmB9GqgFHk\nBzRwDwJ6EcgK5aSDZ2/4TSAjKOMXd3gPh6sTq/+GApG0wkSYdzSBz/AXclUQ+g==\n'