Take or “the ancient game of Nim” is a game where each player removes from one to all sticks in a row inside a pyramid of sticks.
Depending on versions, player who takes last stick or doesn't wins.
This should run on chipmunk basic for the Macintosh, and should probably run on any console-oriented basic also (ubasic, gwbasic, and so on).
10 dim a(3) : dim posi$(50) : puntero = 0 : dim gana(50) 20 for f = 0 to ubound(a) : a(f) = 0 : next 25 print "Calculando posiciones, espere..." 30 goto 110 40 n = ubound(a) 50 a(n) = a(n)+1 60 if a(n) <= (n+1) then 110 70 n = n-1 80 if n < 0 then 180 90 for g = n+1 to ubound(a) : a(g) = a(n)+1 : next g 100 goto 50 110 for f = 0 to ubound(a) 120 posi$(puntero) = posi$(puntero)+chr$(48+a(f)) 130 rem print a(f); 140 next f 150 print posi$(puntero);" "; 160 puntero = puntero+1 170 goto 40 180 puntero = puntero-1 190 print 200 gosub 4000 : print 210 posac$ = posi$(puntero) 220 gosub 5000 225 gosub 8000 230 input "¿Comienza el Humano o el Computador (H/C)? ";r$ 240 if r$ = "H" or r$ = "h" then turno = 1 : goto 280 250 if r$ = "C" or r$ = "c" then turno = 0 : goto 280 260 print "Responda H o C" 270 goto 230 280 if turno = 1 then gosub 6000 : else gosub 7000 290 if posac$ = "0000" then goto 320 300 turno = (turno+1) mod 2 : goto 280 320 print "El "; 330 if turno = 0 then print " computador "; : else print " humano "; 340 print "ha perdido." 350 input "¿Otra partida (S/N)? ";r$ 360 if r$ = "S" or r$ = "s" then goto 210 370 if r$ = "N" or r$ = "n" then end 380 print "Responda 'S' o 'N'." 390 goto 350 2000 rem BUSCAR POSICION 2010 max = puntero : min = 0 2020 n = min+int((max-min)/2) 2030 if posi$(n) = buscame$ then buscap = n : return 2040 if posi$(n) > buscame$ then max = n-1 2050 if posi$(n) < buscame$ then min = n+1 2060 if max >= min then 2020 2070 buscap = -1 : return 3000 rem ORDENAR CADENA 3010 for ford = len(ord$) to 2 step -1 3020 for gord = 1 to ford-1 3030 if mid$(ord$,gord,1) > mid$(ord$,gord+1,1) then m$ = mid$(ord$,gord+1,1)+mid$(ord$,gord,1) : mid$(ord$,gord,2) = m$ 3040 next gord 3050 next ford 3060 return 4000 rem buscar jugadas perdedoras 4010 rem "0" es una jugada ganadora: quien llega a ella, gana. 4020 rem "1" es una jugada perdedora: quien llega a ella, pierde. 4030 rem Todas las jugadas que no permitan llevar al adversario a posición 4040 rem perdedora son posiciones perdedoras. 4050 for f = 0 to puntero : gana(f) = -99 : next 4060 buscame$ = "0000" : gosub 2000 : gana(buscap) = 0 4070 buscame$ = "0001" : gosub 2000 : gana(buscap) = -1 4080 marcados = 0 4090 pact = buscap+1 4100 rem Quitar palitos a cada columna para saber a qué posiciones 4110 rem lleva la posición actual. 4120 rem si la posición actual lleva a alguna posición marcada como 4130 rem gana(xxx)=-99, volver a marcar la posición actual como gana(pact)=-99 4140 rem si la posición actual lleva a alguna posición marcada como perdedora 4150 rem (gana(xxx)=-yyy, mayor que -99), marcarla como ganadora (gana(pact)=xxx 4160 rem en cualquier otro caso, marcar la posición como perdedora (-1) 4170 print "Calculando tabla de movimientos. Espere..." 4180 gana(pact) = -1 : c$ = posi$(pact) : fp = len(c$) 4190 rem print 4200 print posi$(pact);" ";' "=> "; 4210 c$ = posi$(pact) : if mid$(c$,fp,1) = "0" then 4310 4220 mid$(c$,fp,1) = chr$(asc(mid$(c$,fp,1))-1) 4230 ord$ = c$ : gosub 3000 4240 buscame$ = ord$ : gosub 2000 4250 rem print posi$(buscap);", "; 4260 if gana(buscap) = -99 then gana(pact) = -99 : goto 4310 4270 if gana(buscap) < 0 then gana(pact) = buscap : goto 4310 : rem print "[";posi$(buscap);"] "; 4280 rem if gana(buscap) >= 0 then print posi$(buscap);" "; 4290 if mid$(c$,fp,1) > "0" then 4220 4300 fp = fp-1 : if fp > 0 then goto 4210 4310 rem acabando con la posición pact 4320 pact = pact+1 4330 if pact > puntero then goto 4350 4340 goto 4180 4350 rem busca piezas no definidas para repetir el proceso... 4360 pact = 1 4370 if gana(pact) = -99 then print posi$(pact);" no definida." 4380 pact = pact+1 4390 if pact <= puntero then 4370 4400 return 4410 print "Posiciones perdedoras" 4420 for f = 1 to puntero 4430 if gana(f) > 0 then print posi$(f);" "; 4440 next 4450 print "Posiciones perdedoras" 4460 for f = 1 to puntero 4470 if gana(f) < 0 then print posi$(f);" "; 4480 next : print 4490 end 5000 rem dibujar los palitos 5010 print 5020 for fdib = 1 to len(posac$) 5030 print chr$(asc("A")+fdib-1);" "; 5040 for gdib = 1 to asc(mid$(posac$,fdib,1))-48 5050 print "| "; 5060 next gdib 5070 print 5080 next fdib 5090 return 6000 rem Mueve el humano 6005 gosub 5000 6010 input "¿De qué fila va a coger la pieza (escriba la letra de la fila)? ";r$ 6020 r = asc(r$)-asc("A")+1 6030 if r < 1 or r > len(posac$) then print "Filas desde la A hasta la ";chr$(len(posac$)+asc("A")-1);"." : goto 6010 6040 if mid$(posac$,r,1) <= "0" then print "Fila vacía; elija otra." : goto 6010 6050 input "¿Cuántos palitos desea coger (mínimo 1; escriba 0 para cambiar de fila)? ";palitos 6060 if palitos = 0 then print "Bien, escoja otra fila, si así lo desea." : goto 6010 6070 if palitos < 0 then print "Mínimo 1 palito. Para cambiar de fila, escriba 0." : goto 6050 6080 if palitos+asc("0") > asc(mid$(posac$,r,1)) then print "En esa fila sólo hay ";asc(mid$(posac$,r,1))-asc("0");" palitos." : goto 6050 6090 n$ = chr$(asc(mid$(posac$,r,1))-palitos) 6100 mid$(posac$,r,1) = n$ 6110 return 7000 rem Mueve el computador 7010 gosub 5000 7020 ord$ = posac$ : gosub 3000 7030 pcanon$ = ord$ 7040 buscame$ = ord$ : gosub 2000 7050 if buscap = -1 then print "Error interno. El ordenador se rinde." : end 7060 if gana(buscap) >= 0 then 7150 7070 rem no conocemos posición ganadora 7080 print "Me lo pones dificil..." : rem print "debug: elegido al azar." 7090 rem elijamos una al azar. 7100 if posac$ = posi$(0) then print "Pero si no quedan palitos!!" : return 7110 r = int(rnd(len(posac$)))+1 7120 if mid$(posac$,r,1) = "0" then 7110 7130 mid$(posac$,r,1) = chr$(asc(mid$(posac$,r,1))-1) 7140 return 7150 rem Conocemos la posición ganadora 7160 rem su valor está en posi$(gana(buscap)) 7170 ganac$ = posi$(gana(buscap)) 7180 rem Vamos a ver qué cambia entre pcanon (que está ordenada) y 7190 rem ganac$ (que también está ordenada). 7200 rem la diferencia puede consistir en: 7210 rem Hay un cero más en ganac$ => Buscar qué columna falta. 7220 rem Hey el mismo número de ceros => Buscar qué columna baja. 7230 rem print "debugging: comparar ";pcanon$;" con ";ganac$;"." 7240 dim valores(2,10) 7250 for f = 0 to ubound(valores,2) : for g = 0 to 2 : valores(g,f) = 0 : next g : next f 7260 for f = 1 to len(pcanon$) 7270 cifra1 = asc(mid$(pcanon$,f,1))-asc("0") 7280 cifra2 = asc(mid$(ganac$,f,1))-asc("0") 7290 valores(1,cifra1) = valores(1,cifra1)+1 7300 valores(2,cifra2) = valores(2,cifra2)+1 7310 next f 7320 dim vdif(2) : diferencias = 0 : vdif(0) = -1 : vdif(1) = -1 7330 for f = 0 to ubound(valores,2) 7340 if valores(1,f) <> valores(2,f) then vdif(diferencias) = f : diferencias = diferencias+1 7350 next f 7360 if diferencias <> 2 then print "Error." : stop 7370 if diferencias = 0 then print "Error." : stop 7380 m$ = chr$(asc("0")+vdif(0)) 7390 n$ = chr$(asc("0")+vdif(1)) : if m$ < n$ then x$ = m$ : m$ = n$ : n$ = x$ 7400 rem print "Debug: Donde había ";m$;" hay ";n$;"." 7410 f = 1 7420 if mid$(posac$,f,1) = m$ then mid$(posac$,f,1) = n$ : goto 7440 7430 f = f+1 : if f <= len(posac$) then 7420 7440 return 8000 rem REGLAS 8010 input "¿Desea ver las reglas del juego (S/N)?";r$ 8020 if r$ = "S" or r$ = "s" then 8050 8030 if r$ = "N" or r$ = "n" then return 8040 print "Escriba 'S' o 'N'." : goto 8010 8050 print : print "T A K E (también llamado DERNIER o GAME OF NIM)." 8060 print : print "Reglas del juego:" 8070 print "Por turnos, los jugadores toman un palito o más de una sola línea." 8080 print "Pierde el jugador que toma el último palito." 8090 print : print "Estrategia:" 8100 print "Trate de forzar al oponente a llegar a una posición desde la que no" 8110 print "pueda forzarle a vd. a tomar el último palito." 8120 print "En este juego hay MOVIMIENTOS GANADORES y MOVIMIENTOS PERDEDORES." 8130 print "Si juega adecuadamente, el primer jugador siempre gana." 8140 print : return