home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / dtx9302 / neuron / neuron.pas < prev   
Encoding:
Pascal/Delphi Source File  |  1993-03-10  |  13.9 KB  |  615 lines

  1. (* ****************************************************** *)
  2. (*                      NEURON.PAS                        *)
  3. (*            NIMM-SPIEL mit Neuronalem Netz              *)
  4. (*             (c) 1993 Bernd Matzke & DMV                *)                                  *)
  5. (* ****************************************************** *)
  6. PROGRAM Neuron;
  7.  
  8. USES Objects, Drivers, Views, Menus,
  9.      Dialogs, App, MsgBox, Crt;
  10.  
  11.  
  12. CONST
  13.  
  14. cmSpiel  =  101;
  15. cmLernen =  102;
  16. cmAktual =  103;
  17. cmInfo   =  104;
  18. cmClear  =  105;
  19. cm_eins  = 1001;
  20. cm_zwei  = 1002;
  21. cm_drei  = 1003;
  22.  
  23. FileName = 'NEURON.DAT';
  24.  
  25.  
  26. TYPE
  27.  
  28. NetzTyp = ARRAY[1..21,1..3,0..3] OF INTEGER;
  29.  
  30. {speichert Züge eines Spiels}
  31. PZugListe = ^TZugListe;
  32. TZugListe = Object(TCollection)
  33.   PROCEDURE FreeItem(p:POINTER); Virtual;
  34. END;
  35.  
  36. {Spezieller Dialog für Spiel}
  37. PSpielDialog = ^TSpielDialog;
  38. TSpielDialog = Object(TDialog)
  39.   CONSTRUCTOR Init(VAR r:TRect; ATitle: TTitleStr);
  40.   PROCEDURE HandleEvent(VAR Event:TEvent); Virtual;
  41. END;
  42.  
  43. TNetz = Object    {Nachbildung Neuronales Netzwerk}
  44.   nw: NetzTyp;                       { "Neuronen" }
  45.   CONSTRUCTOR Init;
  46.   DESTRUCTOR Done; Virtual;
  47.   FUNCTION vorschlag(anz, alt:INTEGER):INTEGER;
  48.   PROCEDURE lernen(VAR l:PZugListe; w:INTEGER);
  49.   PROCEDURE clear;
  50. END;
  51.  
  52. TSpiel = Object(TApplication)
  53.   Neuron: TNetz;
  54.   alt,                         {vorhergehender Zug}
  55.   anzahl: INTEGER;         {noch vorhandene Steine}
  56.   CONSTRUCTOR Init;
  57.   DESTRUCTOR Done; Virtual;
  58.   PROCEDURE InitStatusLine; Virtual;
  59.   PROCEDURE InitMenuBar; Virtual;
  60.   PROCEDURE HandleEvent(VAR Event:TEvent); Virtual;
  61.   FUNCTION SpielerZug:INTEGER;
  62.   FUNCTION ComputerZug:INTEGER;
  63.   PROCEDURE Spielen;
  64.   PROCEDURE Lernen;
  65.   PROCEDURE ZugMerken(VAR weg:INTEGER;
  66.                       VAR l:PZugListe);
  67.   PROCEDURE InfoBox(s:STRING);
  68. END;
  69.  
  70. {Window für Spielstandanzeige}
  71. PAnzWin = ^TAnzWin; 
  72. TAnzWin = Object(TWindow)
  73.   CONSTRUCTOR Init(r: TRect);
  74. END;
  75.  
  76. {zeigt Spielfeld an}
  77. PSpielstand = ^TSpielstand; 
  78. TSpielstand = Object(TView)
  79.   steine:INTEGER;
  80.   CONSTRUCTOR Init(VAR r: TRect);
  81.   PROCEDURE Draw; Virtual;
  82.   PROCEDURE HandleEvent(VAR Event:TEvent); Virtual;
  83. END;
  84.  
  85. {Window für allgemeine Info}
  86. PInfoWin = ^TInfoWin; 
  87. TInfoWin = Object(TWindow)
  88.   CONSTRUCTOR Init(s:STRING);
  89. END;
  90.  
  91. {Erzeugt allgemeine Info}
  92. PInfo = ^TInfo; 
  93. TInfo = Object(TView)
  94.   info,outp:STRING;
  95.   CONSTRUCTOR Init(VAR r: TRect;s:STRING);
  96.   PROCEDURE Draw;  Virtual;
  97.   PROCEDURE HandleEvent(VAR Event:TEvent); Virtual;
  98. END;
  99.  
  100. {speichert einen Zug}
  101. PZug = ^TZug; 
  102. TZug = RECORD
  103.   altzug,       {vorhergehender Zug}
  104.   anz,          {momentan vorhandene Steine}
  105.   zug: INTEGER; {ausgeführter Zug}
  106. END;
  107.  
  108. { ---------- Allgemeine Proceduren ---------- }
  109.  
  110. {berechnet zulässigen Bereich für folgenden Zug}
  111. PROCEDURE Schranken(VAR alt, unten, oben:INTEGER);
  112. BEGIN
  113.   unten:=1;
  114.   oben:=3;
  115.   IF alt <> 0 THEN BEGIN
  116.     unten:=alt-1;
  117.     IF unten<1 THEN
  118.       unten:=1;
  119.     oben:=alt+1;
  120.     IF oben>3 THEN
  121.       oben:=3;
  122.   END;
  123. END;
  124.  
  125. { ---------- TZugListe ---------- }
  126. PROCEDURE TZugListe.FreeItem;
  127. VAR pp:PZug;
  128. BEGIN
  129.   pp:=p;
  130.   Dispose(pp);
  131. END;
  132.  
  133. { ---------- TSpielDialog ---------- }
  134. CONSTRUCTOR TSpielDialog.Init;
  135. BEGIN
  136.   TDialog.Init(R, ATitle);
  137.   {Dialog hat weder Zoom- noch Schließfeld}
  138.   flags:=flags AND
  139.          NOT(wfGrow OR wfClose OR wfZoom);
  140.   options:=options OR ofCenterY;
  141. END;
  142.  
  143. PROCEDURE TSpielDialog.HandleEvent;
  144. BEGIN
  145.   IF Event.What = evCommand THEN
  146.     CASE Event.command OF
  147.       cm_eins,
  148.       cm_zwei,
  149.       cm_drei   :EndModal(Event.command);
  150.       cmCancel,  {diese Kommandos unterdrücken}
  151.       cmDefault :ClearEvent(Event);
  152.     END;                          
  153.   TDialog.HandleEvent(Event);
  154. END;
  155.  
  156. { ---------- TNetz ---------- }
  157. CONSTRUCTOR TNetz.Init;
  158. VAR f:FILE OF NetzTyp;
  159. BEGIN
  160.   Assign(f, FileName);
  161.   {$I-} Reset(f); {$I+}
  162.   IF IOResult = 0 THEN BEGIN
  163.     Read(f, nw);
  164.     Close(f); END
  165.   ELSE
  166.     TNetz.Clear;  {Anfangsbelegung}
  167. END;
  168.  
  169. DESTRUCTOR TNetz.Done;
  170. VAR  f:FILE OF NetzTyp;
  171. BEGIN
  172.   Assign(f, FileName);
  173.   Rewrite(f);
  174.   Write(f, nw);
  175.   Close(f);
  176. END;
  177.  
  178. {Zug mit höchstem Wert auswählen}
  179. FUNCTION TNetz.vorschlag;
  180. VAR i,           {Laufvariable}
  181.     s,           {selektierter Zug}
  182.     a,           {minimaler Zug}
  183.     e:INTEGER;   {maximaler Zug}
  184. BEGIN
  185.   schranken(alt,a,e);
  186.   s:=a;
  187.   FOR i:=a TO e DO
  188.     IF (nw[anz,i,alt] >= nw[anz,s,alt]) OR
  189.        (nw[anz,i,alt] =  nw[anz,s,alt]) AND
  190.        (Random > 0.6)
  191.     THEN
  192.       s:=i;
  193.   vorschlag:=s;
  194. END;
  195.  
  196. {Spiel auswerten}
  197. PROCEDURE TNetz.lernen; 
  198. VAR n:INTEGER;
  199.     p:PZug;
  200. BEGIN
  201.   FOR n:=0 TO l^.count-1 DO BEGIN
  202.     p:=l^.at(n);
  203.     CASE w OF
  204.       1: IF nw[p^.anz,p^.zug,p^.altzug] < 30
  205.          THEN Inc(nw[p^.anz,p^.zug,p^.altzug]);
  206.       0: IF nw[p^.anz,p^.zug,p^.altzug] > -30
  207.          THEN Dec(nw[p^.anz,p^.zug,p^.altzug]);
  208.     END;
  209.   END;
  210. END;
  211.  
  212. PROCEDURE TNetz.Clear;
  213. BEGIN
  214.   FillChar(nw, SizeOf(nw), Chr(0));
  215. END;
  216.  
  217. { ---------- TSpiel ---------- }
  218. CONSTRUCTOR TSpiel.Init;
  219. BEGIN
  220.   TApplication.Init;
  221.   Neuron.Init;
  222. END;
  223.  
  224. DESTRUCTOR TSpiel.Done;
  225. BEGIN
  226.   Neuron.Done;
  227.   TApplication.Done;
  228. END;
  229.  
  230. PROCEDURE TSpiel.InitStatusLine;
  231. VAR r: TRect;
  232. BEGIN
  233.   GetExtent(r);
  234.   r.A.Y := r.B.Y - 1;
  235.   StatusLine := New(PStatusLine, Init(r,
  236.     NewStatusDef(0, $FFFF,
  237.       NewStatusKey('', kbF10, cmMenu,
  238.       NewStatusKey('~Alt-X~ Exit    ',
  239.                     kbAltX,  cmQuit,
  240.       NewStatusKey('~F4~ Spiel      ',
  241.                     kbF4,    cmSpiel,
  242.       NewStatusKey('~F5~ Lernen     ',
  243.                     kbF5,    cmLernen,
  244.       NewStatusKey('Netzwerk löschen',
  245.                     kbNoKey, cmClear, NIL)
  246.     )))), NIL)
  247.   ));
  248. END;
  249.  
  250. PROCEDURE TSpiel.InitMenuBar;
  251. VAR r:TRect;
  252. BEGIN
  253.   GetExtent(r);
  254.   r.b.y := r.a.y +1;
  255.   Insert(New(PStaticText,
  256.     Init(r, '      Nimm-Spiel mit '+
  257.             'Neuronalem Netz')));
  258. END;
  259.  
  260. PROCEDURE TSpiel.HandleEvent(VAR Event: TEvent);
  261. BEGIN
  262.   TApplication.HandleEvent(Event);
  263.   IF Event.What = evCommand THEN BEGIN
  264.     CASE Event.Command OF
  265.       cmSpiel : Spielen;
  266.       cmLernen: Lernen;
  267.       cmClear : Neuron.Clear;
  268.     ELSE
  269.       EXIT;
  270.     END;
  271.     ClearEvent(Event);
  272.   END;
  273. END;
  274.  
  275.  
  276. PROCEDURE TSpiel.Spielen;
  277. VAR
  278.   r: TRect;
  279.   s:STRING;
  280.   m: POINTER;
  281.   dran:BOOLEAN;
  282.   mn,cn:INTEGER;
  283.   AnzWin: PAnzWin;
  284.   mlist,clist: PZugListe;
  285.   li:LONGINT;
  286. BEGIN
  287.   r.Assign(2,2,30,17);
  288.   AnzWin := New(PAnzWin, Init(r));
  289.   Desktop^.Insert(AnzWin);
  290.   Randomize;
  291.   anzahl:=10+Random(12);
  292.   m:=message(Desktop, evBroadcast, cmAktual,
  293.              Addr(anzahl));
  294.   alt:=0;
  295.   dran:=Odd(Random(2));
  296.   mlist:=New(PZugListe, Init(5,1));
  297.   clist:=New(PZugListe, Init(5,1));
  298.   WHILE anzahl > 0 DO BEGIN
  299.     IF dran THEN BEGIN
  300.       IF alt-1 <= anzahl THEN BEGIN
  301.         mn:= SpielerZug;
  302.         ZugMerken(mn, mlist);
  303.         anzahl:= anzahl- mn;
  304.         m:=message(Desktop, evBroadcast,
  305.                    cmAktual, Addr(anzahl));
  306.         IF anzahl=0 THEN BEGIN
  307.           InfoBox('Sie haben verloren !!!');
  308.           Neuron.lernen(mlist,0);
  309.           Neuron.lernen(clist,1);
  310.         END; END
  311.       ELSE BEGIN
  312.         InfoBox('Sie können nicht setzen !');
  313.         InfoBox('Ich habe verloren !!!');
  314.         Neuron.lernen(mlist,1);
  315.         Neuron.lernen(clist,0);
  316.         anzahl:=0;
  317.       END;
  318.       dran:=NOT dran;
  319.       alt:=mn; END
  320.     ELSE BEGIN
  321.       IF alt-1 <= anzahl THEN BEGIN
  322.         cn:=ComputerZug;
  323.         li:=cn;
  324.         FormatStr(s,'Ich nehme: %d',li);
  325.         InfoBox(s);
  326.         ZugMerken(cn, clist);
  327.         anzahl:=anzahl-cn;
  328.         m:=message(Desktop, evBroadcast,
  329.                    cmAktual, Addr(anzahl));
  330.         IF anzahl=0 THEN BEGIN
  331.           InfoBox('Ich habe verloren !!!');
  332.           Neuron.lernen(mlist,1);
  333.           Neuron.lernen(clist,0);
  334.         END; END
  335.       ELSE BEGIN
  336.         InfoBox('Ich kann nicht setzen !');
  337.         InfoBox('Sie haben verloren !!!');
  338.         Neuron.lernen(mlist,0);
  339.         Neuron.lernen(clist,1);
  340.         anzahl:=0;
  341.       END;
  342.       dran:=NOT dran;
  343.       alt:=cn;
  344.     END;
  345.   END;
  346.   Dispose(AnzWin,Done);
  347.   Dispose(clist,Done);
  348.   Dispose(mlist,Done);
  349. END;
  350.  
  351. {wie TSpiel.spielen, ohne Bildschirmausgaben }
  352. PROCEDURE TSpiel.Lernen;
  353. VAR
  354.   m:POINTER;
  355.   dran:BOOLEAN;
  356.   mn,cn:INTEGER;
  357.   mlist,clist: PZugListe;
  358.   n:LONGINT;
  359.   InfoWin: PInfoWin;
  360. BEGIN
  361.   InfoWin:=New(PinfoWin,
  362.     Init('Netz anlernen, %d. Versuch'));
  363.   Desktop^.Insert(InfoWin);
  364.   FOR n:=1 TO 500 DO BEGIN
  365.     Randomize;
  366.     anzahl:=10+Random(12);
  367.     alt:=0;
  368.     dran:=Odd( Random(2));
  369.     mlist:=New( PZugListe, Init(5,1));
  370.     clist:=New( PZugListe, Init(5,1));
  371.     WHILE anzahl > 0 DO BEGIN
  372.       IF dran THEN BEGIN
  373.         IF alt-1 <= anzahl THEN BEGIN
  374.           mn:=ComputerZug;
  375.           ZugMerken(mn,mlist);
  376.           anzahl:=anzahl-mn;
  377.           IF anzahl=0 THEN BEGIN
  378.             Neuron.lernen(mlist,0);
  379.             Neuron.lernen(clist,1);
  380.           END; END
  381.         ELSE BEGIN
  382.           Neuron.lernen(mlist,1);
  383.           Neuron.lernen(clist,0);
  384.           anzahl:=0;
  385.         END;
  386.         dran:=NOT dran;
  387.         alt:=mn; END
  388.       ELSE BEGIN
  389.         IF alt-1 <= anzahl THEN BEGIN
  390.           cn:=ComputerZug;
  391.           ZugMerken(cn,clist);
  392.           anzahl:=anzahl-cn;
  393.           IF anzahl=0 THEN BEGIN
  394.             Neuron.lernen(mlist,1);
  395.             Neuron.lernen(clist,0);
  396.           END; END
  397.         ELSE BEGIN
  398.           Neuron.lernen(mlist,0);
  399.           Neuron.lernen(clist,1);
  400.           anzahl:=0;
  401.         END;
  402.         dran:=NOT dran;
  403.         alt:=cn;
  404.       END;
  405.     END;
  406.     Dispose(clist,Done);
  407.     Dispose(mlist,Done);
  408.     m:=Message(Desktop, evBroadcast, cmInfo, @n);
  409.     Delay(10);
  410.   END;
  411.   Dispose(InfoWin,Done);
  412. END;
  413.  
  414. FUNCTION TSpiel.SpielerZug;
  415. VAR r:TRect;
  416.     d:PSpielDialog;
  417.     erg,
  418.     unten,
  419.     oben,
  420.     y:INTEGER;
  421. BEGIN
  422.   Schranken(alt,unten,oben);
  423.   IF oben > anzahl THEN
  424.     oben:=anzahl;
  425.   r.Assign(40, 0, 65, 3*(oben-unten+1) +2);
  426.   d:=New(PSpielDialog, Init(r,'Sie nehmen:'));
  427.   y:=2;
  428.   WITH d^ DO BEGIN
  429.     IF 1 IN [unten..oben] THEN BEGIN
  430.       r.Assign(3,y,18,y+2);
  431.       Insert( New( PButton,Init(
  432.         r,'~E~in Stein',cm_eins,bfNormal)));
  433.       y:=y+3;
  434.     END;
  435.     IF 2 IN [unten..oben] THEN BEGIN
  436.       r.Assign(3,y,18,y+2);
  437.       Insert( New( PButton,Init(
  438.         r,'~Z~wei Steine',cm_zwei,bfNormal)));
  439.       y:=y+3;
  440.     END;
  441.     IF 3 IN [unten..oben] THEN BEGIN
  442.       r.Assign(3,y,18,y+2);
  443.       Insert( New( PButton,Init(
  444.         r,'~D~rei Steine',cm_drei,bfNormal)));
  445.     END;
  446.   END;
  447.   CASE Desktop^.execview(d) OF
  448.     cm_eins: SpielerZug:=1;
  449.     cm_zwei: SpielerZug:=2;
  450.     cm_drei: SpielerZug:=3;
  451.   END;
  452.   Dispose(d,Done);
  453. END;
  454.  
  455. FUNCTION TSpiel.ComputerZug;
  456. VAR msg,unten,oben,v:INTEGER;
  457. BEGIN
  458.   v:=Neuron.vorschlag(anzahl,alt);
  459.   IF v > anzahl THEN
  460.     v:=anzahl;
  461.   ComputerZug:=v;
  462. END;
  463.  
  464. PROCEDURE TSpiel.ZugMerken;
  465. VAR p:PZug;
  466. BEGIN
  467.   New(p);
  468.   p^.anz:=anzahl;
  469.   p^.zug:=weg;
  470.   p^.altzug:=alt;
  471.   l^.Insert(p);
  472. END;
  473.  
  474. {Anzeige einer Info für kurze Zeit}
  475. PROCEDURE TSpiel.InfoBox;
  476. VAR m:POINTER;
  477.     info:PInfoWin;
  478. BEGIN
  479.   Desktop^.Lock;
  480.   info:=New(PInfoWin,Init(s));
  481.   Desktop^.Insert(info);
  482.   info^.MoveTo(35,5);
  483.   m:=message(Desktop, evBroadcast,
  484.              cmInfo, NIL);
  485.   Desktop^.UnLock;
  486.   Sound(1000);
  487.   Delay(100);
  488.   NoSound;
  489.   Delay(1500);
  490.   Dispose(info, Done);
  491. END;
  492.  
  493. { ---------- TSpielstand ---------- }
  494. CONSTRUCTOR TSpielstand.Init;
  495. BEGIN
  496.   TView.Init(r);
  497.   Options := Options OR ofFramed;
  498.   EventMask:=EventMask OR evBroadcast;
  499.   steine:=0;
  500. END;
  501.  
  502. PROCEDURE TSpielstand.Draw;
  503. VAR i, j, zeile, st:INTEGER;
  504. BEGIN
  505.   FOR i:=0 TO size.y -1 DO    
  506.     WriteChar(0, i, ' ', 1, size.x);
  507.   zeile:=size.y-2;
  508.   st:=steine;
  509.   WHILE st > 0 DO BEGIN
  510.     FOR j:=6 DOWNTO 1 DO BEGIN
  511.       FOR i:=1 TO j DO BEGIN
  512.         IF st > 0 THEN
  513.           WriteChar(14 - 2*j + 4*(i-1), zeile,
  514.                     '█', 6, 2);  {#219}
  515.         Dec(st);
  516.       END;
  517.       Dec(zeile, 2);
  518.     END;
  519.   END;
  520. END;
  521.  
  522. PROCEDURE TSpielstand.HandleEvent;
  523. {Anzeige Spielstand nur auf Kommando}
  524. BEGIN
  525.   TView.HandleEvent(Event);
  526.   IF Event.What = evBroadcast THEN BEGIN
  527.     CASE Event.Command OF
  528.       cmAktual:BEGIN
  529.         steine:=INTEGER(Event.Infoptr^);
  530.         draw;
  531.       END;
  532.     ELSE
  533.       EXIT;
  534.     END;
  535.     ClearEvent(Event);
  536.   END;
  537. END;
  538.  
  539. { ---------- TAnzWin ---------- }
  540. CONSTRUCTOR TAnzWin.Init;
  541. VAR Spielstand: PSpielstand;
  542. BEGIN
  543.   TWindow.Init(r, 'Spielstand', WnNoNumber);
  544.   flags:= flags AND
  545.           NOT(wfGrow OR wfClose OR wfZoom);
  546.   palette:= wpBlueWindow;
  547.   options:=options OR ofCenterY;
  548.   EventMask:= EventMask OR evBroadcast;
  549.   GetClipRect(r);
  550.   r.Grow(-1,-1);
  551.   Spielstand:= New(PSpielstand, Init(r));
  552.   Insert(Spielstand);
  553. END;
  554.  
  555. { ---------- TInfo ---------- }
  556. {Anzeige allgemeiner Infos auf Kommando}
  557. CONSTRUCTOR TInfo.Init;
  558. BEGIN
  559.   TView.Init(r);
  560.   GrowMode := gfGrowHiX + gfGrowHiY;
  561.   Options := Options OR ofFramed;
  562.   EventMask:=EventMask OR evBroadcast;
  563.   info:=s;       {String mit Formatangaben}
  564. END;
  565.  
  566. PROCEDURE TInfo.Draw;
  567. VAR i:INTEGER;
  568. BEGIN
  569.   FOR i:=0 TO size.y -1 DO
  570.     WriteChar(0, i, ' ', 2, size.x);
  571.   WriteStr(1, size.y DIV 2-1, outp, 2);
  572. END;
  573.  
  574. PROCEDURE TInfo.HandleEvent;
  575. BEGIN
  576.   TView.HandleEvent(Event);
  577.   IF Event.What = evBroadcast THEN BEGIN
  578.     CASE Event.Command OF
  579.       cmInfo:BEGIN
  580.         FormatStr(outp,info,Event.Infoptr^);
  581.         Draw;
  582.       END;
  583.     ELSE
  584.       EXIT;
  585.     END;
  586.     ClearEvent(Event);
  587.   END;
  588. END;
  589.  
  590. { ---------- TInfoWin ---------- }
  591. CONSTRUCTOR TInfoWin.Init;
  592. VAR Info: PInfo;
  593.     R:TRect;
  594. BEGIN
  595.   R.Assign(1,1,40,5);
  596.   TWindow.Init(r, '', WnNoNumber);
  597.   flags:= flags AND
  598.           NOT(wfGrow OR wfClose OR wfZoom);
  599.   options:= options OR ofCentered;
  600.   palette:= wpGrayWindow;
  601.   EventMask:= EventMask OR evBroadcast;
  602.   GetClipRect(r);
  603.   r.Grow(-1,-1);
  604.   Info:= New(PInfo, Init(r,s));
  605.   Insert(Info);
  606. END;
  607.  
  608. VAR Spiel: TSpiel;
  609.  
  610. BEGIN
  611.   Spiel.Init;
  612.   Spiel.Run;
  613.   Spiel.Done;
  614. END.
  615.