home *** CD-ROM | disk | FTP | other *** search
- (***********************************************************************
- Strategiespiel KALAHA
- (c) by Günter Rau
- Pfullinger Str. 87
- 7000 Stuttgart 70
-
- Usage:
- KALAHA [OFF]
-
- Der optionale Parameter gibt an, ob der Lautsprecher eingeschaltet sein
- soll oder nicht. (OFF muß groß geschrieben sein!)
-
- ************************************************************************)
-
-
- program kalaha;
- uses constkal,slavekal,crt;
-
- type
- wertebereich = 0..steine;
- tzug = 1..feldlen;
- tzugfolge = record
- folge : array[1..maxzug] of tzug;
- anzahl: 0..maxzug;
- end;
- tspieler = (computer,mensch);
- tfeld = record
- feld : array[1..feldlen] of wertebereich;
- kalaha: wertebereich;
- end;
- tspielstand = record
- brett : array[tspieler] of tfeld;
- amzug: tspieler;
- end;
- inoutfeld = record
- x0,y0 : integer;
- hoehe,breite : integer;
- end;
-
- var
- anfangsstand,
- endstand : tspielstand;
- gewinner : tspieler;
- gegner : array[tspieler] of tspieler;
- ende,beep : boolean;
- staerke : integer;
-
- procedure init;
- var i :integer;
- begin
- with brett do begin
- x0 := 5; y0 := 1; xabstand := 5; yabstand := 0; breite := 10; hoehe := 3;
- kalaha1[1] := x0; kalaha1[2] := y0;
- kalaha2[1] := x0; kalaha2[2] := y0+(feldlen+1)*(yabstand+hoehe);
- for i := 1 to feldlen do
- begin
- feld1[i,1] := x0; feld1[i,2] := y0 + (yabstand + hoehe)*i;
- feld2[i,1] := x0+breite+xabstand; feld2[i,2] := y0 + (yabstand + hoehe)*i;
- end;
- with infofeld do begin
- x0 := 32; y0 := 22;
- breite := 46; hoehe := 3;
- end;
- with computerinfo do begin
- x0 := 32; y0 := 1;
- breite := 46; hoehe := 3;
- end;
- end;
- gegner[computer] := mensch ; gegner[mensch] := computer;
- spielbrettaufbau;
- end;
-
- procedure Start;
- var
- i : integer;
- antwort : char;
- spieler : tspieler;
- begin
- repeat
- infoausgabe('Wer beginnt, Mensch oder Computer ? (m/c) ');
- antwort := readkey;
- if antwort = chr(27) then antwort := 'e';
- until antwort in ['m','M','c','C','e'];
- if antwort <> 'e' then begin
- infoausgabe('Eingabe der Spielstärke (0..10) ');
- readln(staerke);
- end;
- with anfangsstand do
- begin
- case antwort of
- 'c','C' : amzug := computer;
- 'm','M' : amzug := mensch;
- 'e' : begin ende := true; amzug := computer; end;
- end;
- for spieler := computer to mensch do
- begin
- brett[spieler].kalaha := 0;
- for i := 1 to feldlen do
- brett[spieler].feld[i] := steine div (2*feldlen);
- end;
- end;
- end;
-
- procedure partie;
- var
- spielstand : tspielstand;
- zug : tzug;
-
- function zulaessig(zug : tzug; spieler:tspieler;stand:tspielstand) :
- boolean;
- begin
- zulaessig := stand.brett[spieler].feld[zug] > 0;
- end;
-
- procedure ausgabe(stand : tspielstand);
- var
- i : tzug;
- spieler : tspieler;
- begin
- gotoxy(brett.x0 + (brett.breite*2 + brett.xabstand) div 2,brett.y0+1);
- write(stand.brett[computer].kalaha:2);
- for i := 1 to feldlen do
- begin
- gotoxy(brett.feld1[i,1]+brett.breite div 2-1,brett.feld1[i,2]+1);
- write(stand.brett[mensch].feld[i]:2);
- gotoxy(brett.feld2[i,1]+brett.breite div 2-1,brett.feld2[i,2]+1);
- write(stand.brett[computer].feld[feldlen - i + 1]:2);
- end;
- gotoxy(brett.x0 + (brett.breite*2 + brett.xabstand) div 2,brett.y0 +
- (feldlen+1)*(brett.yabstand+brett.hoehe)+1);
- write(stand.brett[mensch].kalaha:2);
- end; (* of ausgabe *)
-
- function spielende(stellung : tspielstand) : boolean;
- var
- i,sum : integer;
- begin
- sum := 0;
- with stellung do
- for i := 1 to feldlen do
- inc(sum,brett[amzug].feld[i]);
- spielende := sum = 0;
- end;
-
- procedure erzeuge(var neu:tspielstand; zug:tzug; alt:tspielstand;
- anzeige : boolean);
- var
- zugsteine : wertebereich;
- index : 0..feldlen;
- ich,gegenspieler,spieler : tspieler;
- procedure ziehe;
- begin
- if beep then begin
- sound(300);
- delay(100);
- nosound;
- end;
- delay(300);
- end;
- begin
- neu := alt;
- index := zug;
- with alt do
- begin
- zugsteine := brett[amzug].feld[zug];
- ich := amzug;
- end;
- gegenspieler := gegner[ich];
- spieler := ich;
- neu.brett[spieler].feld[index] := 0;
- if (spieler = mensch) and anzeige then begin
- gotoxy(brett.feld1[index,1]+brett.breite div 2-1,
- brett.feld1[index,2]+1);
- write(neu.brett[spieler].feld[index]:2);ziehe;
- end;
- if (spieler = computer) and anzeige then begin
- gotoxy(brett.feld2[feldlen-index+1,1]+brett.breite div 2-1,
- brett.feld2[feldlen-index+1,2]+1);
- write(neu.brett[spieler].feld[index]:2);ziehe;
- end;
- neu.amzug := gegenspieler;
- repeat
- if index < feldlen then
- begin
- index := index + 1;
- if (zugsteine = 1) and
- (neu.brett[spieler].feld[index] = 0) and
- (spieler = ich) then
- begin
- inc(neu.brett[spieler].kalaha,
- neu.brett[gegenspieler].feld[feldlen - index +1]+1);
- if (spieler = computer) and anzeige then begin
- gotoxy(brett.x0 + (brett.breite*2 + brett.xabstand) div 2,brett.y0+1);
- write(neu.brett[spieler].kalaha:2);ziehe;
- end;
- if (spieler = mensch) and anzeige then begin
- gotoxy(brett.x0 + (brett.breite*2 + brett.xabstand) div 2,brett.y0 +
- (feldlen+1)*(brett.yabstand+brett.hoehe)+1);
- write(neu.brett[spieler].kalaha:2);ziehe;
- end;
- neu.brett[gegenspieler].feld[feldlen - index + 1] := 0;
- if (gegenspieler = mensch) and anzeige then begin
- gotoxy(brett.feld1[feldlen - index + 1,1]+brett.breite div 2-1,
- brett.feld1[feldlen - index + 1,2]+1);
- write(neu.brett[gegenspieler].feld[feldlen - index + 1]:2);ziehe;
- end;
- if (gegenspieler = computer) and anzeige then begin
- gotoxy(brett.feld2[index,1]+brett.breite div 2-1,
- brett.feld2[index,2]+1);
- write(neu.brett[gegenspieler].feld[feldlen - index + 1]:2);ziehe;
- end;
- end
- else
- begin
- inc(neu.brett[spieler].feld[index],1);
- if (spieler = mensch) and anzeige then begin
- gotoxy(brett.feld1[index,1]+brett.breite div 2-1,
- brett.feld1[index,2]+1);
- write(neu.brett[spieler].feld[index]:2);ziehe;
- end;
- if (spieler = computer) and anzeige then begin
- gotoxy(brett.feld2[feldlen-index+1,1]+brett.breite div 2-1,
- brett.feld2[feldlen-index+1,2]+1);
- write(neu.brett[spieler].feld[index]:2);ziehe;
- end;
- end;
- dec(zugsteine,1);
- end
- else
- begin
- if spieler = ich then
- begin
- if zugsteine = 1 then
- neu.amzug := ich;
- inc(neu.brett[spieler].kalaha,1);
- if (spieler = computer) and anzeige then begin
- gotoxy(brett.x0 + (brett.breite*2 + brett.xabstand) div 2,brett.y0+1);
- write(neu.brett[spieler].kalaha:2);ziehe;
- end;
- if (spieler = mensch) and anzeige then begin
- gotoxy(brett.x0 + (brett.breite*2 + brett.xabstand) div 2,brett.y0 +
- (feldlen+1)*(brett.yabstand+brett.hoehe)+1);
- write(neu.brett[spieler].kalaha:2);ziehe;
- end;
- dec(zugsteine,1);
- index := 0;
- end
- else
- begin
- index := 0;
- end;
- spieler := gegner[spieler];
- end;
- until zugsteine = 0;
- end; (* of erzeuge *)
-
- procedure derMenschZieht(var stellung : tspielstand);
- var
- antwort : char;
- eingabeEnde : boolean;
- begin
- eingabeEnde := false;
- repeat
- repeat
- infoausgabe('Sie sind am Zug, welches Feld ? ');
- antwort := readkey;
- until antwort in (['1' .. '6' ] + [chr(27)]);
- if antwort = chr(27) then
- begin
- ende := true;
- eingabeEnde := true;
- end
- else
- begin
- zug := ord(antwort) - ord('0');
- if zulaessig(zug,mensch,stellung) then
- begin
- eingabeEnde := true;
- erzeuge(stellung,zug,stellung,true);
- end;
- end;
- until eingabeEnde;
- end; (* of derMenschZieht *)
-
- procedure derComputerZieht(var stellung : tspielstand);
- var
- zugfolge,bestfolge : tzugfolge;
- bestwert,wert : integer;
- i : integer;
- ans : char;
- endermittle : boolean;
-
- function wertung(stand:tspielstand; zfolge:tzugfolge) : integer;
- var
- endstand : tspielstand;
- i : integer;
- spieler : tspieler;
- begin (* wertung *)
- spieler := stand.amzug;
- endstand := stand;
- for i := 1 to zfolge.anzahl do
- erzeuge(endstand,zfolge.folge[i],endstand,false);
- wertung := endstand.brett[spieler].kalaha -
- stand.brett[spieler].kalaha;
- end; (* of wertung *)
-
- function maxwert(start : tspielstand) : integer;
- var
- max,wert : integer;
- spieler : tspieler;
- bestzug : tzugfolge;
-
- procedure analyse(var bestzug : tzugfolge; altstand:tspielstand);
- var
- probezug : tzug;
- neustand : tspielstand;
- begin
- for probezug := 1 to feldlen do
- begin
- if altstand.amzug = spieler then
- begin
- if zulaessig(probezug,spieler,altstand) then
- begin
- inc(bestzug.anzahl,1);
- erzeuge(neustand,probezug,altstand,false);
- bestzug.folge[bestzug.anzahl] := probezug;
- analyse(bestzug,neustand);
- dec(bestzug.anzahl,1);
- end;
- end
- else
- begin
- wert := wertung(start,bestzug);
- if max < wert then max := wert;
- end;
- end;
- end; (* of analyse *)
-
- begin (* maxwert *)
- bestzug.anzahl := 0;
- max := 0;
- spieler := start.amzug;
- analyse(bestzug,start);
- maxwert := max;
- end; (* of maxwert *)
-
- procedure ermittle( var bestzug : tzugfolge; stand : tspielstand);
- var
- probezug : integer;
- i : integer;
- neustand : tspielstand;
- ans : char;
- begin (* ermittle *)
- if spielende(stand) then
- begin
- endermittle := true;
- end;
- probezug := 1;
- while (probezug <= feldlen) and (not endermittle) do
- begin
- if stand.amzug = computer then
- begin
- if zulaessig(probezug,computer,stand) then
- begin
- inc(bestzug.anzahl,1);
- erzeuge(neustand,probezug,stand,false);
- bestzug.folge[bestzug.anzahl] := probezug;
- ermittle(bestzug,neustand);
- dec(bestzug.anzahl,1);
- end;
- end
- else
- begin
- wert := wertung(stellung,bestzug)-maxwert(stand);
- if bestwert < wert then
- begin
- bestwert := wert;
- bestfolge := bestzug;
- end;
- if bestwert >= staerke then endermittle := true;
- end;
- inc(probezug,1);
- end; (* of while *)
- end; (* of ermittle *)
-
- begin (* derComputerZieht *)
- bestwert := -100;
- infoausgabe('der Computer zieht ... ');
- cinfoausgabe(' ');
- zugfolge.anzahl := 0; bestfolge.anzahl := 0;
- endermittle := false;
- ermittle(zugfolge,stellung);
- infoausgabe('fertig mit rechnen, drücke CR ');
- ans := readkey;
- cinfoausgabe('Zugfolge : ');
- for i := 1 to bestfolge.anzahl do write(bestfolge.folge[i]:2,' ');
- for i := 1 to bestfolge.anzahl do
- begin
- infoausgabe('Zug Nummer : ');write(i:2,' Drücke CR ');
- ans := readkey;
- erzeuge(stellung,bestfolge.folge[i],stellung,true);
- (* if i <> bestfolge.anzahl then
- ausgabe(stellung); *)
- end;
- cinfoausgabe(' ');
- stellung.amzug := mensch;
- end; (* of derComputerZieht *)
-
- begin (* Partie *)
- spielstand := anfangsstand;
- endstand := spielstand;
- ausgabe(spielstand);
-
- while (not spielende(spielstand)) and (not ende) do
- begin
- case spielstand.amzug of
- computer : derComputerZieht(spielstand);
- mensch : derMenschzieht(spielstand);
- end;
- endstand := spielstand;
- (* ausgabe(spielstand); *)
- end;
- end; (* of Partie *)
-
- procedure gewinnentscheidung;
- var csteine,msteine,i : integer;
- begin
- csteine := 0; msteine := 0;
- for i := 1 to feldlen do
- begin
- csteine := csteine + endstand.brett[computer].feld[i];
- msteine := msteine + endstand.brett[mensch].feld[i];
- end;
- csteine := csteine + endstand.brett[computer].kalaha;
- msteine := msteine + endstand.brett[mensch].kalaha;
- if msteine = csteine then
- cinfoausgabe('unentschieden');
- if msteine > csteine then
- cinfoausgabe('Sie haben gewonnen ! ');
- if msteine < csteine then
- cinfoausgabe('Der Computer hat gewonnen ! ');
- end;
-
- begin (* main *)
- beep := true;
- if paramcount > 0 then begin
- if paramstr(1) = 'OFF' then beep := false;
- end;
- ende := false;
- Beschreibung;
- init;
- repeat
- start;
- partie;
- gewinnentscheidung;
- until ende;
- end.