Browse Source

Version 2.20

tags/2.20
Carsten Larsen 2 years ago
parent
commit
d8238b8649
59 changed files with 5898 additions and 2 deletions
  1. 191
    0
      Abacus.cpp
  2. 51
    0
      Abacus.hpp
  3. 145
    0
      About.cpp
  4. 57
    0
      About.hpp
  5. 534
    0
      Board.cpp
  6. 126
    0
      Board.hpp
  7. 867
    0
      BoardClass.cpp
  8. 80
    0
      BoardClass.hpp
  9. 263
    0
      BoardWindow.cpp
  10. 51
    0
      BoardWindow.hpp
  11. 96
    0
      Board_testmain.cpp
  12. 53
    0
      Images.hpp
  13. 371
    0
      LocStrings.h
  14. 59
    0
      MCC.hpp
  15. 141
    0
      Main.cpp
  16. 108
    0
      MsgWin.cpp
  17. 52
    0
      MsgWin.hpp
  18. 11
    2
      README.md
  19. 118
    0
      Rules.cpp
  20. 57
    0
      Rules.hpp
  21. 253
    0
      Settings.cpp
  22. 62
    0
      Settings.hpp
  23. 90
    0
      Status.hpp
  24. 186
    0
      StatusWin.cpp
  25. 85
    0
      StatusWin.hpp
  26. 42
    0
      System.hpp
  27. 352
    0
      Tools.cpp
  28. 113
    0
      Tools.hpp
  29. 63
    0
      images/IMG_Abacus.c
  30. BIN
      images/IMG_Abacus.iff
  31. 73
    0
      images/IMG_About.c
  32. 87
    0
      images/IMG_Kreis_A.c
  33. BIN
      images/IMG_Kreis_A.iff
  34. 87
    0
      images/IMG_Kreis_B.c
  35. BIN
      images/IMG_Kreis_B.iff
  36. 60
    0
      images/IMG_Load.c
  37. BIN
      images/IMG_Load.iff
  38. 80
    0
      images/IMG_Logo.c
  39. BIN
      images/IMG_Logo.iff
  40. 242
    0
      images/IMG_Moves.c
  41. BIN
      images/IMG_Moves.iff
  42. 111
    0
      images/IMG_Prefs.c
  43. BIN
      images/IMG_Prefs.iff
  44. 60
    0
      images/IMG_Quit.c
  45. BIN
      images/IMG_Quit.iff
  46. 60
    0
      images/IMG_Rules.c
  47. BIN
      images/IMG_Rules.iff
  48. 52
    0
      images/IMG_Save.c
  49. BIN
      images/IMG_Save.iff
  50. 60
    0
      images/IMG_Settings.c
  51. BIN
      images/IMG_Settings.iff
  52. 60
    0
      images/IMG_Start.c
  53. BIN
      images/IMG_Start.iff
  54. 60
    0
      images/IMG_Stop.c
  55. BIN
      images/IMG_Stop.iff
  56. 69
    0
      images/IMG_Time.c
  57. BIN
      images/IMG_Time.iff
  58. 60
    0
      images/IMG_Undo.c
  59. BIN
      images/IMG_Undo.iff

+ 191
- 0
Abacus.cpp View File

@@ -0,0 +1,191 @@
/*
* This file is part of Abacus.
* Copyright (C) 1997 Kai Nickel
*
* Abacus is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Abacus is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Abacus. If not, see <http://www.gnu.org/licenses/>.
*
*/
/****************************************************************************************
Abacus.cpp
-----------------------------------------------------------------------------------------

CL_Abacus (Application)

-----------------------------------------------------------------------------------------
01.01.1997
****************************************************************************************/

#include "Abacus.hpp"
#include "BoardWindow.hpp"
#include "Settings.hpp"
#include "About.hpp"
#include "Rules.hpp"
#include "Tools.hpp"


MUI_CustomClass *CL_Abacus;



/****************************************************************************************
About
****************************************************************************************/

ULONG Abacus_About(struct IClass* cl, Object* obj, Msg msg)
{
struct Abacus_Data* data = (Abacus_Data*)INST_DATA(cl, obj);
setatt(data->WI_About, MUIA_Window_RefWindow, data->WI_Main);
setatt(data->WI_About, MUIA_Window_Open , TRUE);
return 0;
}


/****************************************************************************************
Rules
****************************************************************************************/

ULONG Abacus_Rules(struct IClass* cl, Object* obj, Msg msg)
{
struct Abacus_Data* data = (Abacus_Data*)INST_DATA(cl, obj);
setatt(data->WI_Rules, MUIA_Window_Open, TRUE);
return 0;
}


/****************************************************************************************
OpenSettings
****************************************************************************************/

ULONG Abacus_OpenSettings(struct IClass* cl, Object* obj, Msg msg)
{
struct Abacus_Data* data = (Abacus_Data*)INST_DATA(cl, obj);
setatt(data->WI_Settings, MUIA_Window_Open, TRUE);
return 0;
}


/****************************************************************************************
New
****************************************************************************************/

ULONG Abacus_New(struct IClass* cl, Object* obj, struct opSet* msg)
{
Abacus_Data tmp;
obj = (Object*)DoSuperNew(cl, obj,
MUIA_Application_Title , "Abacus",
MUIA_Application_Version , version_string,
MUIA_Application_Copyright , "(c)1995-97, Kai Nickel",
MUIA_Application_Author , "Kai Nickel",
MUIA_Application_Description, GetStr(MSG_APPDESCRIPTION),
MUIA_Application_Base , "ABACUS",
MUIA_Application_HelpFile , "Abacus.guide",

MUIA_Application_Window,
tmp.WI_Main = (Object*)NewObject(CL_BoardWindow->mcc_Class, NULL, TAG_DONE),

MUIA_Application_Window,
tmp.WI_Settings = (Object*)NewObject(CL_Settings->mcc_Class , NULL, TAG_DONE),

MUIA_Application_Window,
tmp.WI_About = (Object*)NewObject(CL_About->mcc_Class , NULL,
TAG_DONE),

MUIA_Application_Window,
tmp.WI_Rules = (Object*)NewObject(CL_Rules->mcc_Class , NULL, TAG_DONE),

TAG_MORE, msg->ops_AttrList);

if (obj)
{
struct Abacus_Data* data = (Abacus_Data*)INST_DATA(cl, obj);
*data = tmp;

DoMethod(obj, MUIM_Application_Load, MUIV_Application_Load_ENVARC);
DoMethod(obj, MUIM_Application_Save, MUIV_Application_Save_ENV);
setatt(obj, MUIA_Abacus_Settings, xget(data->WI_Settings, MUIA_Settings_Settings));
// erste Settings installieren

setatt(tmp.WI_Main, MUIA_Window_Open, TRUE);

return((ULONG)obj);
}
ShowError(NULL, NULL, MSG_NOAPP);
return(0);
}


/****************************************************************************************
Dispose
****************************************************************************************/

ULONG Abacus_Dispose(struct IClass* cl, Object* obj, Msg msg)
{
struct Abacus_Data* data = (Abacus_Data*)INST_DATA(cl, obj);
return(DoSuperMethodA(cl, obj, msg));
}


/****************************************************************************************
Get / Set
****************************************************************************************/

ULONG Abacus_Get(struct IClass* cl, Object* obj, struct opGet* msg)
{
struct Abacus_Data* data = (Abacus_Data*)INST_DATA(cl, obj);
switch (msg->opg_AttrID)
{
case MUIA_Abacus_Settings:
{
Settings* s = (Settings*)xget(data->WI_Settings, MUIA_Settings_Settings);
*(msg->opg_Storage) = (ULONG)s;
return(TRUE);
}
}
return(DoSuperMethodA(cl, obj, (Msg)msg));
}

ULONG Abacus_Set(struct IClass* cl, Object* obj, struct opSet* msg)
{
struct Abacus_Data* data = (Abacus_Data*)INST_DATA(cl, obj);
struct TagItem *tag;
tag = FindTagItem(MUIA_Abacus_Settings, msg->ops_AttrList);
if (tag)
{
DoMethod(data->WI_Main, MUIM_BoardWindow_NewSettings);
}
return(DoSuperMethodA(cl, obj, (Msg)msg));
}

/****************************************************************************************
Dispatcher
****************************************************************************************/

SAVEDS ASM ULONG Abacus_Dispatcher(REG(a0) struct IClass* cl,
REG(a2) Object* obj,
REG(a1) Msg msg)
{
switch(msg->MethodID)
{
case OM_NEW : return(Abacus_New (cl, obj, (opSet*)msg));
case OM_DISPOSE : return(Abacus_Dispose (cl, obj, msg));
case OM_GET : return(Abacus_Get (cl, obj, (opGet*)msg));
case OM_SET : return(Abacus_Set (cl, obj, (opSet*)msg));
case MUIM_Abacus_EditSettings: return(Abacus_OpenSettings (cl, obj, msg));
case MUIM_Abacus_About : return(Abacus_About (cl, obj, msg));
case MUIM_Abacus_Rules : return(Abacus_Rules (cl, obj, msg));
}
return(DoSuperMethodA(cl, obj, msg));
}


+ 51
- 0
Abacus.hpp View File

@@ -0,0 +1,51 @@
/*
* This file is part of Abacus.
* Copyright (C) 1997 Kai Nickel
*
* Abacus is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Abacus is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Abacus. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef INCLUDE_ABACUS_HPP
#define INCLUDE_ABACUS_HPP
/****************************************************************************************
Abacus.hpp
-----------------------------------------------------------------------------------------



-----------------------------------------------------------------------------------------
29.12.1996
****************************************************************************************/

#include "MCC.hpp"


#define MUIA_Abacus_Settings (TAGBASE_KAI | 0x1001)
#define MUIM_Abacus_EditSettings (TAGBASE_KAI | 0x1003)
#define MUIM_Abacus_About (TAGBASE_KAI | 0x1004)
#define MUIM_Abacus_Rules (TAGBASE_KAI | 0x1005)

extern MUI_CustomClass *CL_Abacus;


struct Abacus_Data
{
Object *WI_Main, *WI_Settings, *WI_About, *WI_Rules;
};


SAVEDS ASM ULONG Abacus_Dispatcher(REG(a0) struct IClass* cl,
REG(a2) Object* obj,
REG(a1) Msg msg);
#endif

+ 145
- 0
About.cpp View File

@@ -0,0 +1,145 @@
/*
* This file is part of Abacus.
* Copyright (C) 1997 Kai Nickel
*
* Abacus is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Abacus is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Abacus. If not, see <http://www.gnu.org/licenses/>.
*
*/
/****************************************************************************************
About.cpp
-----------------------------------------------------------------------------------------

CL_About (Window)

-----------------------------------------------------------------------------------------
01.01.1996
****************************************************************************************/

#include "About.hpp"
#include "Tools.hpp"
#include "Images.hpp"
#include <stdio.h> // für sprintf

MUI_CustomClass *CL_About;


/****************************************************************************************
AboutMUI
****************************************************************************************/

ULONG About_AboutMUI(struct IClass* cl, Object* obj, Msg msg)
{
struct About_Data* data = (About_Data*)INST_DATA(cl, obj);
Object* app = (Object*)xget(obj, MUIA_ApplicationObject);
Object* aboutwin = AboutmuiObject,
MUIA_Window_RefWindow , obj,
MUIA_Aboutmui_Application, app,
End;
if (aboutwin) setatt(aboutwin, MUIA_Window_Open, TRUE);
return 0;
}


/****************************************************************************************
New
****************************************************************************************/

ULONG About_New(struct IClass* cl, Object* obj, struct opSet* msg)
{
Object *BT_Ok, *BT_MUI;
About_Data tmp;

static char version_text[50];
sprintf(version_text, GetStr(MSG_ABOUT_VERSION), version_number, version_date);

obj = (Object*)DoSuperNew(cl, obj,
MUIA_HelpNode , "COPYRIGHT",
MUIA_Window_LeftEdge , MUIV_Window_LeftEdge_Centered,
MUIA_Window_TopEdge , MUIV_Window_TopEdge_Centered,
MUIA_Window_CloseGadget, FALSE,
MUIA_Window_DepthGadget, FALSE,
MUIA_Window_SizeGadget , FALSE,
MUIA_Window_DragBar , FALSE,
MUIA_Window_Borderless , TRUE,

WindowContents, VGroup, ButtonFrame,

Child, HGroup,
Child, HVSpace,
Child, MakeImage(IMG_Logo_body, IMG_LOGO_WIDTH, IMG_LOGO_HEIGHT,
IMG_LOGO_DEPTH, IMG_LOGO_COMPRESSION, IMG_LOGO_MASKING,
IMG_Abacus_colors),
Child, VGroup,
Child, MakeImage(IMG_Abacus_body, IMG_ABACUS_WIDTH, IMG_ABACUS_HEIGHT,
IMG_ABACUS_DEPTH, IMG_ABACUS_COMPRESSION,
IMG_ABACUS_MASKING, IMG_Abacus_colors),
Child, TextObject,
MUIA_Text_Contents, version_text,
MUIA_Font , MUIV_Font_Tiny,
End,
End,
Child, HVSpace,
End,

Child, HBar(),

Child, HGroup,
Child, HVSpace,
Child, TextObject,
MUIA_Text_Contents, GetStr(MSG_ABOUT_TEXT),
End,
Child, HVSpace,
End,

Child, HBar(),
Child, HGroup,
Child, BT_Ok = MakeButton(MSG_ABOUT_OK , MSG_ABOUT_OK_HELP ),
Child, BT_MUI = MakeButton(MSG_ABOUT_MUI, MSG_ABOUT_MUI_HELP),
End,

End,

TAG_MORE, msg->ops_AttrList);

if (obj)
{
DoMethod(obj , MUIM_Notify, MUIA_Window_CloseRequest, TRUE , obj, 3, MUIM_Set, MUIA_Window_Open, FALSE);
DoMethod(BT_Ok , MUIM_Notify, MUIA_Pressed , FALSE, obj, 3, MUIM_Set, MUIA_Window_Open, FALSE);
DoMethod(BT_MUI, MUIM_Notify, MUIA_Pressed , FALSE, obj, 1, MUIM_About_AboutMUI);



struct About_Data* data = (About_Data*)INST_DATA(cl, obj);
*data = tmp;
return (ULONG)obj;
}
return 0;
}


/****************************************************************************************
Dispatcher
****************************************************************************************/

SAVEDS ASM ULONG About_Dispatcher(REG(a0) struct IClass* cl,
REG(a2) Object* obj,
REG(a1) Msg msg)
{
switch(msg->MethodID)
{
case OM_NEW : return(About_New (cl, obj, (opSet*)msg));
case MUIM_About_AboutMUI: return(About_AboutMUI(cl, obj, msg));
}
return DoSuperMethodA(cl, obj, msg);
}

+ 57
- 0
About.hpp View File

@@ -0,0 +1,57 @@
/*
* This file is part of Abacus.
* Copyright (C) 1997 Kai Nickel
*
* Abacus is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Abacus is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Abacus. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef INCLUDE_ABOUT_HPP
#define INCLUDE_ABOUT_HPP
/****************************************************************************************
About.hpp
-----------------------------------------------------------------------------------------

Interface des About-Fenster

-----------------------------------------------------------------------------------------
02.12.1996
****************************************************************************************/

#include "MCC.hpp"

extern MUI_CustomClass *CL_About;

#define MUIM_About_AboutMUI (TAGBASE_KAI | 0x1402)



/******************************************************************************
About_Data
******************************************************************************/

struct About_Data
{
Object *dummy;
};


/******************************************************************************
Dispatcher
******************************************************************************/

SAVEDS ASM ULONG About_Dispatcher(REG(a0) struct IClass* cl,
REG(a2) Object* obj,
REG(a1) Msg msg);

#endif

+ 534
- 0
Board.cpp View File

@@ -0,0 +1,534 @@
/*
* This file is part of Abacus.
* Copyright (C) 1997 Kai Nickel
*
* Abacus is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Abacus is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Abacus. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*****************************************************************************************
Board.cpp
------------------------------------------------------------------------------------------



------------------------------------------------------------------------------------------
03.01.1997
*****************************************************************************************/

#include "Board.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


/*****************************************************************************************
statische Elemente
*****************************************************************************************/

const char Board::black = 'O';
const char Board::white = 'X';
const char Board::empty = '.';

const int Board::next[61][6] =
{
{-1, -1, 1, 6, 5, -1}, {-1, -1, 2, 7, 6, 0}, {-1, -1, 3, 8, 7, 1}, // 00
{-1, -1, 4, 9, 8, 2}, {-1, -1, -1, 10, 9, 3}, {-1, 0, 6, 12, 11, -1}, // 03
{ 0, 1, 7, 13, 12, 5}, { 1, 2, 8, 14, 13, 6}, { 2, 3, 9, 15, 14, 7}, // 06
{ 3, 4, 10, 16, 15, 8}, { 4, -1, -1, 17, 16, 9}, {-1, 5, 12, 19, 18, -1}, // 09
{ 5, 6, 13, 20, 19, 11}, { 6, 7, 14, 21, 20, 12}, { 7, 8, 15, 22, 21, 13}, // 12
{ 8, 9, 16, 23, 22, 14}, { 9, 10, 17, 24, 23, 15}, {10, -1, -1, 25, 24, 16}, // 15
{-1, 11, 19, 27, 26, -1}, {11, 12, 20, 28, 27, 18}, {12, 13, 21, 29, 28, 19}, // 18
{13, 14, 22, 30, 29, 20}, {14, 15, 23, 31, 30, 21}, {15, 16, 24, 32, 31, 22}, // 21
{16, 17, 25, 33, 32, 23}, {17, -1, -1, 34, 33, 24}, {-1, 18, 27, 35, -1, -1}, // 24
{18, 19, 28, 36, 35, 26}, {19, 20, 29, 37, 36, 27}, {20, 21, 30, 38, 37, 28}, // 27
{21, 22, 31, 39, 38, 29}, {22, 23, 32, 40, 39, 30}, {23, 24, 33, 41, 40, 31}, // 30
{24, 25, 34, 42, 41, 32}, {25, -1, -1, -1, 42, 33}, {26, 27, 36, 43, -1, -1}, // 33
{27, 28, 37, 44, 43, 35}, {28, 29, 38, 45, 44, 36}, {29, 30, 39, 46, 45, 37}, // 36
{30, 31, 40, 47, 46, 38}, {31, 32, 41, 48, 47, 39}, {32, 33, 42, 49, 48, 40}, // 39
{33, 34, -1, -1, 49, 41}, {35, 36, 44, 50, -1, -1}, {36, 37, 45, 51, 50, 43}, // 42
{37, 38, 46, 52, 51, 44}, {38, 39, 47, 53, 52, 45}, {39, 40, 48, 54, 53, 46}, // 45
{40, 41, 49, 55, 54, 47}, {41, 42, -1, -1, 55, 48}, {43, 44, 51, 56, -1, -1}, // 48
{44, 45, 52, 57, 56, 50}, {45, 46, 53, 58, 57, 51}, {46, 47, 54, 59, 58, 52}, // 51
{47, 48, 55, 60, 59, 53}, {48, 49, -1, -1, 60, 54}, {50, 51, 57, -1, -1, -1}, // 54
{51, 52, 58, -1, -1, 56}, {52, 53, 59, -1, -1, 57}, {53, 54, 60, -1, -1, 58}, // 57
{54, 55, -1, -1, -1, 59} // 60
};

/*
Spielfeld:
00 01 02 03 04

05 06 07 08 09 10

11 12 13 14 15 16 17

18 19 20 21 22 23 24 25

26 27 28 29 30 31 32 33 34

35 36 37 38 39 40 41 42

43 44 45 46 47 48 49

50 51 52 53 54 55

56 57 58 59 60

Richtungen:

0 1

5 X 2

4 3
*/


/*****************************************************************************************
Kon- /Destruktor
*****************************************************************************************/

Board::Board()
{
Clear();
}


/*****************************************************************************************
Dir
*****************************************************************************************/

int Board::Dir(int a, int b)
{
for (int i = 0; i < 6; i++)
if (next[a][i] == b) return i;
return -1;
}


/*****************************************************************************************
outBalls()
*****************************************************************************************/

int Board::outBalls(char player) const
{
return (player == white) ? outwhite : outblack;
}


/*****************************************************************************************
Clear
*****************************************************************************************/

void Board::Clear()
{
strcpy(field, "XXXXXXXXXXX..XXX.............................OOO..OOOOOOOOOOO");
me = white;
you = black;
outwhite = 0;
outblack = 0;
value = 0;
}


/*****************************************************************************************
Show
*****************************************************************************************/

/*
#include <iostream.h>

void Board::Show() const
{
int o = 0, i, j;
for (i = 5; i < 10; i++)
{
for (j = 0; j < 10 - i; j++) cout << " ";
for (j = 0; j < i; j++) cout << field[o + j] << " ";
o += i;
cout << "\n";
}
for (i = 8; i >= 5; i--)
{
for (j = 0; j < 10 - i; j++) cout << " ";
for (j = 0; j < i; j++) cout << field[o + j] << " ";
o += i;
cout << "\n";
}
};
*/


/*****************************************************************************************
Save / Load
*****************************************************************************************/

BOOL Board::Save(char* filename)
{
BOOL ok = FALSE;
FILE* f = fopen(filename, "w");
if (f)
{
ok = (fwrite(this, 1, sizeof(Board), f) == sizeof(Board));
fclose(f);
}
return ok;
}

BOOL Board::Load(char* filename)
{
BOOL ok = FALSE;
FILE* f = fopen(filename, "r");
if (f)
{
ok = (fread(this, 1, sizeof(Board), f) == sizeof(Board));
fclose(f);
}
return ok;
}


/*****************************************************************************************
Test
*****************************************************************************************/

int Board::Test1(int ball1, int dir) const
{
int pos = next[ball1][dir];
if (pos == -1) return -1; // O-
if (field[pos] == you ) return -2; // OX
if (field[pos] == empty) return 0; // O.
// OO
pos = next[pos][dir];
if (pos == -1) return -1; // OO-
if (field[pos] == empty) return 0; // OO.
if (field[pos] == you ) // OOX
{
pos = next[pos][dir];
if (pos == -1) return 1; // OOX-
if (field[pos] == empty) return 0; // OOX.
return -2; // OOXO oder OOXX
} // OOO

pos = next[pos][dir];
if (pos == -1) return -1; // OOO-
if (field[pos] == empty) return 0; // OOO.
if (field[pos] == me ) return -5; // OOOO
// OOOX
pos = next[pos][dir];
if (pos == -1) return 1; // OOOX-
if (field[pos] == empty) return 0; // OOOX.
if (field[pos] == me ) return -5; // OOOXO
// OOOXX
pos = next[pos][dir];
if (pos == -1) return 1; // OOOXX-
if (field[pos] == empty) return 0; // OOOXX.
return -5; // OOOXXX oder OOOXXO
};

int Board::Test(int ball1, int dir, int ball2, int ball3) const
{
if (ball2 != -1)
{
if (next[ball2][dir] == -1) return -1;
if (field[next[ball2][dir]] != empty) return -3;
if (ball3 != -1)
{
if (next[ball3][dir] == -1) return -1;
if (field[next[ball3][dir]] != empty) return -3;
}
if (next[ball1][dir] == -1) return -1;
if (field[next[ball1][dir]] != empty) return -3;
return 0;
}
else
{
return Test1(ball1, dir);
}
};


/*****************************************************************************************
Move
*****************************************************************************************/

#include <iostream.h>

char Board::ChangePosTo(int pos, char neu)
{
char alt = field[pos];
if (alt == neu) return alt;
field[pos] = neu;

int r = 0, a = 0, n = 0;
for (int dir = 0; dir < 6; dir++)
{
int x = next[pos][dir];
if (x == -1) r += 4;
else if (field[x] == alt) a += 2;
else if (field[x] == neu) n += 2;
}

if (alt == white) value += r - a;
else if (alt == black) value += a - r;

if (neu == white) value += n - r;
else if (neu == black) value += r - n;

return alt;
}


void Board::Move1(int ball1, int dir)
{
/*
** Toggle player
*/

char tmp = me;
me = you;
you = tmp;

/*
** Reihe pushen
*/

tmp = empty;

do
{
tmp = ChangePosTo(ball1, tmp);
if (tmp == empty) return; // Ende der Reihe

ball1 = next[ball1][dir];
if (ball1 == -1) // Ende des Brettes
{
if (me == black)
{
value += 1000;
outblack++;
}
else
{
value -= 1000;
outwhite++;
}
return;
}
}
while (TRUE);
}

void Board::Move(int ball1, int dir, int ball2, int ball3)
{
if (ball2 != -1)
{
ChangePosTo(next[ball1][dir], me );
ChangePosTo(ball1 , empty);
ChangePosTo(next[ball2][dir], me );
ChangePosTo(ball2 , empty);
if (ball3 != -1)
{
ChangePosTo(next[ball3][dir], me );
ChangePosTo(ball3 , empty);
}

char tmp = me;
me = you;
you = tmp;
}
else
{
Move1(ball1, dir);
}
}


/*****************************************************************************************
Evaluate
*****************************************************************************************/

inline int Board::Evaluate() const
{
return (me == white) ? value : - value;
}


/*****************************************************************************************
AlphaBeta
*****************************************************************************************/

const int INFINITY = 20000;

int Board::AlphaBeta(int depth, int alpha, int beta) const
{
depth--;
int best = - INFINITY;
Board b;

for (int pos = 60; pos >= 0; pos--)
{
if (field[pos] == me)
{
for (int dir = 5; dir >= 0; dir--)
{
if (Test1(pos, dir) >= 0)
{
b = *this;
b.Move1(pos, dir);

int v;
if (depth)
v = - b.AlphaBeta(depth, -beta, -alpha);
else
v = - b.Evaluate();

if (v > best)
{
best = v;
if (best >= beta) return best;
if (best > alpha) alpha = best;
}

}
}
}
}

return best;
}


/*****************************************************************************************
PrincipalVariation
*****************************************************************************************/

int Board::PrincipalVariation(int depth, int alpha, int beta)
{
if (!depth) return Evaluate();
depth--;
int dir = 5, pos = -1;

Board b = *this;
b.NextMove(pos, dir);
int best = - b.PrincipalVariation(depth, -beta, -alpha);

while (b.NextMove(pos, dir) && best < beta)
{
if (best > alpha) alpha = best;
int value = - b.PrincipalVariation(depth, -alpha - 1, -alpha);
if (value > alpha && value < beta)
best = - b.PrincipalVariation(depth, -beta, -value);
else if (value > best)
best = value;

b = *this;
}

return best;
}


/*****************************************************************************************
ComputerMove
*****************************************************************************************/

void Board::Computer_Move(Status& status, int tiefe)
{
status.Update(0, (14 - outBalls(me))*6);
int nr = 1;

/*
** Zufallsfeld erzeugen
*/

int rpos[61], p, dest;
for (p = 0; p < 61; p++) rpos[p] = -1;
for (p = 0; p < 61; p++)
{
do {dest = Random(61);}
while (rpos[dest] != -1);
rpos[dest] = p;
}

int rdir[6];
for (p = 0; p < 6; p++) rdir[p] = -1;
for (p = 0; p < 6; p++)
{
do {dest = Random(6);}
while (rdir[dest] != -1);
rdir[dest] = p;
}


/*
** Alle Möglichkeiten testen
*/

int best = - INFINITY;
Board bestboard;
tiefe--;

for (p = 0; p < 61 && !status.Break(); p++)
{
int pos = rpos[p];
if (field[pos] == me)
{
for (int d = 0; d < 6 && !status.Break(); d++)
{
status.Update(nr++);
int dir = rdir[d];
if (Test1(pos, dir) >= 0)
{
Board b = *this;
b.Move1(pos, dir);
int test;
if (tiefe)
test = - b.AlphaBeta(tiefe, -INFINITY, +INFINITY);
else
test = - b.Evaluate();
if (test > best)
{
best = test;
bestboard = b;
}
} // if Test1 >= 0
} // for dir
} // if me
} // for pos

*this = bestboard;
};


/*****************************************************************************************
Sucessors
*****************************************************************************************/

BOOL Board::NextMove(int &pos, int &dir)
{
do
{
dir++;
if (dir == 6)
{
dir = 0;
pos++;
if (pos == 61) return FALSE;
}
}
while (field[pos] != me || Test1(pos, dir) < 0);
Move1(pos, dir);
return TRUE;
}

+ 126
- 0
Board.hpp View File

@@ -0,0 +1,126 @@
/*
* This file is part of Abacus.
* Copyright (C) 1997 Kai Nickel
*
* Abacus is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Abacus is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Abacus. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef INCLUDE_BOARD_HPP
#define INCLUDE_BOARD_HPP
/*****************************************************************************************
Board.hpp
------------------------------------------------------------------------------------------



------------------------------------------------------------------------------------------
03.01.1997
*****************************************************************************************/

#include "Status.hpp"


class Board
{
public:

char field[62]; // Spielfeld
char me, you; // Aktiver Spieler und Gegenspieler

static const char black;
static const char white;
static const char empty;
static const int next[61][6];

Board();

int outBalls(char player) const;

/*
** Initialisierung mit Startboard
*/

void Clear();

/*
** Brett als ASCII-Kunstwerk nach cout schicken
*/

//void Show() const;

/*
** Testet, ob Zug legal ist.
** Es wird vorausgesetzt, dass alle drei Kugeln von der
** selben Farbe sind und in einer Reihe liegen. Sonst aber nichts.
**
** Rueckgabewert: 1 eine Kugel des Gegeners flog raus
** 0 keine Kugel folg raus
** -1 Fehler: eigene Kugel(n) rausgeschmissen
** -2 Fehler: keine Uebermacht
** -3 Fehler: seitlich nicht leer
** -5 Fehler: sonstiges
*/

int Test(int, int dir, int, int) const;

/*
** Fuehrt Zug ungeprueft aus
*/

void Move(int, int dir, int, int);

/*
** Fuehrt Zug fuer 'me' aus
*/

void Computer_Move(Status& status, int depth);

/*
** Speichern und Laden
*/

BOOL Save(char* filename);
BOOL Load(char* filename);

/*
** Retourniert Richtung, in der sich b von a befindet (oder -1)
*/

static int Dir(int a, int b);

private:

int outwhite, outblack; // Anz. der verlorenen Kugeln
int value; // Bewertungsindex für white

char ChangePosTo(int pos, char neu); // Ändert Position in neue Farbe und
// retourniert alte. Führt randwhite/black
// mit.


int Test1 (int, int dir) const;
void Move1 (int, int dir);

int Evaluate() const;

int AlphaBeta(int depth, int alpha, int beta) const;

int PrincipalVariation(int depth, int alpha, int beta);



BOOL NextMove(int &pos, int &dir);

};
#endif

+ 867
- 0
BoardClass.cpp View File

@@ -0,0 +1,867 @@
/*
* This file is part of Abacus.
* Copyright (C) 1997 Kai Nickel
*
* Abacus is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Abacus is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Abacus. If not, see <http://www.gnu.org/licenses/>.
*
*/
/****************************************************************************************
BoardClass.cpp
-----------------------------------------------------------------------------------------

CL_Board (Area)

-----------------------------------------------------------------------------------------
01.01.1997
****************************************************************************************/

#include <graphics/gfxmacros.h>
#include <pragma/graphics_lib.h>
#include <pragma/exec_lib.h> // Wait
#include <stdio.h>

#include "BoardClass.hpp"
#include "BoardWindow.hpp"
#include "Abacus.hpp"
#include "Tools.hpp"
#include "Settings.hpp"
#include "StatusWin.hpp"
#include "MsgWin.hpp"

MUI_CustomClass *CL_Board;



/****************************************************************************************
Board_Data
****************************************************************************************/

const int ALLDRAW = 1; // Kugeln und Auskugeln zeichnen
const int SELSDRAW = 3; // Selektionen zeichnen

void Board_Data::GetCenterOf(int nr, int &cx, int &cy)
{
float x = nr, y;
if (nr < 5) {y = 0.1; x += 2.1;};
else if (nr < 11) {y = 1.1; x -= 5; x += 1.6;};
else if (nr < 18) {y = 2.1; x -= 11; x += 1.1;};
else if (nr < 26) {y = 3.1; x -= 18; x += 0.6;};
else if (nr < 35) {y = 4.1; x -= 26; x += 0.1;};
else if (nr < 43) {y = 5.1; x -= 35; x += 0.6;};
else if (nr < 50) {y = 6.1; x -= 43; x += 1.1;};
else if (nr < 56) {y = 7.1; x -= 50; x += 1.6;};
else {y = 8.1; x -= 56; x += 2.1;};
cx = left + rx + int(x * dx),
cy = top + ry + int(y * dy);
}

int Board_Data::GetNrOf(int x, int y)
{
float my = float(y - top ) / float(dy);
if (my < 0 || my >= 9) return -1;
int ball, maxx;
switch(my)
{
case 0: ball = 0; maxx = 4; break;
case 1: ball = 5; maxx = 5; break;
case 2: ball = 11; maxx = 6; break;
case 3: ball = 18; maxx = 7; break;
case 4: ball = 26; maxx = 8; break;
case 5: ball = 35; maxx = 7; break;
case 6: ball = 43; maxx = 6; break;
case 7: ball = 50; maxx = 5; break;
case 8: ball = 56; maxx = 4; break;
}
float mx = float(x - left - (8-maxx) * dx / 2) / float(dx);
if (mx < 0 || mx >= maxx + 1) return -1;
ball += mx;
return ball;
}

ULONG Board_Data::ActivePlayerNr()
{
if (board.me == Board::white)
return 1;
else
return 2;
}


/****************************************************************************************
NewSettings
****************************************************************************************/

ULONG Board_NewSettings(struct IClass* cl, Object* obj, Msg msg)
{
struct Board_Data *data = (Board_Data*)INST_DATA(cl,obj);
data->newsettings = TRUE;
data->diff = FALSE;
data->update_mode = ALLDRAW;
MUI_Redraw(obj, MADF_DRAWUPDATE);
data->setsels = TRUE;
data->update_mode = SELSDRAW;
MUI_Redraw(obj, MADF_DRAWUPDATE);
return 0;
}

/****************************************************************************************
NewGame
****************************************************************************************/

ULONG Board_NewGame(struct IClass* cl, Object* obj, Msg msg)
{
struct Board_Data *data = (Board_Data*)INST_DATA(cl,obj);
Board b;
setatt(obj, MUIA_Board_Board, &b);
return 0;
}


/****************************************************************************************
Load / Save
****************************************************************************************/

ULONG Board_Load(struct IClass* cl, Object* obj, Msg msg)
{
struct Board_Data* data = (Board_Data*)INST_DATA(cl, obj);
Object* app = (Object*)xget(obj, MUIA_ApplicationObject);
char* fname = GetFilename(_win(obj), FALSE, MSG_LOAD_TITLE, "", "Games/");
if (fname)
{
Board b;
if (b.Load(fname))
setatt(obj, MUIA_Board_Board, &b);
else
ShowError(app, obj, MSG_LOAD_ERROR);
}

return 0;
}

ULONG Board_Save(struct IClass* cl, Object* obj, Msg msg)
{
struct Board_Data* data = (Board_Data*)INST_DATA(cl, obj);
Object* app = (Object*)xget(obj, MUIA_ApplicationObject);

char* fname = GetFilename(_win(obj), TRUE, MSG_SAVE_TITLE, "", "Games/");
if (fname)
{
if (!data->board.Save(fname))
ShowError(app, obj, MSG_SAVE_ERROR);
}
return 0;
}


/****************************************************************************************
Undo
****************************************************************************************/

ULONG Board_Undo(struct IClass* cl, Object* obj, Msg msg)
{
struct Board_Data *data = (Board_Data*)INST_DATA(cl,obj);
Board n = data->last_board;
setatt(obj, MUIA_Board_Board, &n);
return 0;
}


/****************************************************************************************
TogglePlayer
****************************************************************************************/

ULONG Board_Winner(struct IClass* cl, Object* obj, Msg msg)
{
struct Board_Data* data = (Board_Data*)INST_DATA(cl, obj);
Object* win = (Object*)xget(obj, MUIA_WindowObject);
Object* app = (Object*)xget(obj, MUIA_ApplicationObject);
Settings* s = (Settings*)xget(app, MUIA_Abacus_Settings);

setatt(win, MUIA_Window_Sleep, TRUE);

char buffer[100];
if (data->board.outBalls(Board::black) == 6)
sprintf(buffer, GetStr(MSG_WINNER_TEXT), s->name1);
else
sprintf(buffer, GetStr(MSG_WINNER_TEXT), s->name2);

Object* mwin = (Object*)NewObject(CL_MsgWin->mcc_Class, NULL,
MUIA_Window_RefWindow , win,
MUIA_MsgWin_MsgBig , GetStr(MSG_WINNER_TITLE),
MUIA_MsgWin_MsgSmall , buffer,
TAG_DONE);
if (!mwin) return 0;

DoMethod(app, OM_ADDMEMBER, mwin);
setatt(mwin, MUIA_Window_Open, TRUE);

ULONG sigs = 0;
while (DoMethod(app, MUIM_Application_NewInput, &sigs) != MUIV_MsgWin_Close)
{
if (sigs) sigs = Wait(sigs);
}

setatt(mwin, MUIA_Window_Open, FALSE);
DoMethod(app, OM_REMMEMBER, mwin);
DisposeObject(mwin);

DoMethod(obj, MUIM_Board_NewGame);

setatt(win, MUIA_Window_Sleep, FALSE);
return 0;
}


/****************************************************************************************
ComputerMove
****************************************************************************************/

ULONG Board_ComputerMove(struct IClass* cl, Object* obj, Msg msg)
{
struct Board_Data* data = (Board_Data*)INST_DATA(cl, obj);
Object* win = (Object*)xget(obj, MUIA_WindowObject);
Object* app = (Object*)xget(obj, MUIA_ApplicationObject);
Settings* s = (Settings*)xget(app, MUIA_Abacus_Settings);

setatt(app, MUIA_Application_Sleep, TRUE);

Board undo = data->last_board;
data->last_board = data->board; //wg. Diffsdraw

if (s->depth2 > 2)
{
StatusWin_Status status(app, win);
status.Init();
data->board.Computer_Move(status, s->depth2);
status.Exit();
}
else
{
Status status;
data->board.Computer_Move(status, s->depth2);
}

data->diff = TRUE;
data->update_mode = ALLDRAW;
MUI_Redraw(obj, MADF_DRAWUPDATE);

if (data->board.outBalls(data->board.me) == 6)
{
DoMethod(obj, MUIM_Board_Winner);
}
else
{
setatt(win, MUIA_BoardWindow_ActivePlayer, data->ActivePlayerNr());

if (s->auto2)
{
if (data->ActivePlayerNr() == 2)
{
DoMethod(app, MUIM_Application_PushMethod,
obj, 1, MUIM_Board_ComputerMove);
}
else
data->last_board = undo;
}
}

setatt(app, MUIA_Application_Sleep, FALSE);
return 0;
}


/****************************************************************************************
AskMinMax
****************************************************************************************/

SAVEDS ULONG Board_AskMinMax(struct IClass* cl,
Object* obj,
struct MUIP_AskMinMax* msg)
{
DoSuperMethodA(cl, obj, (Msg)msg);
msg->MinMaxInfo->MinWidth += 200;
msg->MinMaxInfo->DefWidth += 300;
msg->MinMaxInfo->MaxWidth += MUI_MAXMAX;
msg->MinMaxInfo->MinHeight += 100;
msg->MinMaxInfo->DefHeight += 200;
msg->MinMaxInfo->MaxHeight += MUI_MAXMAX;
return 0;
}


/****************************************************************************************
Setup / Cleanup
****************************************************************************************/

SAVEDS ULONG Board_Setup(struct IClass* cl, Object* obj, Msg msg)
{
if (!DoSuperMethodA(cl, obj, msg)) return(FALSE);
struct Board_Data *data = (Board_Data*)INST_DATA(cl,obj);

MUI_RequestIDCMP(obj, IDCMP_MOUSEBUTTONS);
return TRUE;
}

SAVEDS ULONG Board_Cleanup(struct IClass* cl, Object* obj, Msg msg)
{
struct Board_Data *data = (Board_Data*)INST_DATA(cl,obj);
MUI_ReleasePen(muiRenderInfo(obj), data->pen1); data->pen1 = -1;
MUI_ReleasePen(muiRenderInfo(obj), data->pen2); data->pen2 = -1;
MUI_ReleasePen(muiRenderInfo(obj), data->pen3); data->pen3 = -1;
MUI_ReleasePen(muiRenderInfo(obj), data->pen4); data->pen4 = -1;
data->newsettings = TRUE; // damit die Pens nachher wieder allokiert werden

MUI_RejectIDCMP(obj,IDCMP_MOUSEBUTTONS);
return(DoSuperMethodA(cl, obj, msg));
}


/****************************************************************************************
Handle_Input
****************************************************************************************/

SAVEDS ULONG Board_HandleInput(struct IClass* cl,
Object* obj,
struct MUIP_HandleInput* msg)
{
Object* app = (Object*)xget(obj, MUIA_ApplicationObject);
Object* win = (Object*)xget(obj, MUIA_WindowObject);
struct Board_Data *data = (Board_Data*)INST_DATA(cl,obj);

if ( !msg->imsg ||
(!(msg->imsg->Class == IDCMP_MOUSEBUTTONS) &&
!(msg->imsg->Class == IDCMP_MOUSEMOVE ))
) return(DoSuperMethodA(cl, obj, (Msg)msg));

int ball = data->GetNrOf(msg->imsg->MouseX, msg->imsg->MouseY);
if (ball == -1) return(DoSuperMethodA(cl, obj, (Msg)msg));

switch (msg->imsg->Class)
{
/*
**
** IDCMP_MOUSEBUTTONS
**
*/

case IDCMP_MOUSEBUTTONS:
{
switch (msg->imsg->Code)
{
/*
** SELECTDOWN
*/

case SELECTDOWN:
{
/*
** Erste Selektion
*/

if (data->ball[0] == -1)
{
if (data->board.field[ball] == data->board.me)
{
data->ball[0] = ball;
data->update_mode = SELSDRAW;
data->setsels = TRUE;
MUI_Redraw(obj, MADF_DRAWUPDATE);
MUI_RequestIDCMP(obj, IDCMP_MOUSEMOVE);
}
}

/*
** Selektion canceln
*/
else if (data->ball[0] == ball ||
data->ball[1] == ball ||
data->ball[2] == ball)
{
data->setsels = FALSE;
data->update_mode = SELSDRAW;
MUI_Redraw(obj, MADF_DRAWUPDATE);
data->ball[0] = -1;
data->ball[1] = -1;
data->ball[2] = -1;
}
/*
** Zweite Selektion (Richtung)
*/
else
{
int dir = Board::Dir(data->ball[0], ball);
if (dir != -1 &&
data->board.Test(data->ball[0], dir, data->ball[1], data->ball[2]) >= 0)
{
// Selektionen löschen

data->setsels = FALSE;
data->update_mode = SELSDRAW;
MUI_Redraw(obj, MADF_DRAWUPDATE);

// Zug ausführen

data->last_board = data->board;
data->board.Move(data->ball[0], dir, data->ball[1], data->ball[2]);
data->ball[0] = -1;
data->ball[1] = -1;
data->ball[2] = -1;
data->diff = TRUE;
data->update_mode = ALLDRAW;
MUI_Redraw(obj, MADF_DRAWUPDATE);

if (data->board.outBalls(data->board.me) == 6)
{
DoMethod(obj, MUIM_Board_Winner);
}
else
{
setatt(win, MUIA_BoardWindow_ActivePlayer, data->ActivePlayerNr());

Settings* s = (Settings*)xget(app, MUIA_Abacus_Settings);
if (s->auto2)
{
DoMethod(app, MUIM_Application_PushMethod,
obj, 1, MUIM_Board_ComputerMove);
}
}

}
}
break;
} // End SELECTDOWN

/*
** SELECTUP
*/

case SELECTUP:
{
MUI_RejectIDCMP(obj, IDCMP_MOUSEMOVE);
break;
} // End SELECTUP

} // End UP/DOWN case
break;
} // End IDCMP_MOUSEBUTTONS


/*
**
** IDCMP_MOUSEMOVE
**
*/

case IDCMP_MOUSEMOVE:
{
char me = data->board.me;
int b1 = -1, b2 = -1;
for (int i = 0; i < 6; i++)
{
int n = Board::next[data->ball[0]][i];
if (n == ball)
{
b1 = ball;
if (data->board.field[b1] != me) b1 = -1; // nur eigene
}
else if (n != -1 && Board::next[n][i] == ball)
{
b1 = n;
b2 = ball;
if (data->board.field[b1] != me) {b1 = -1; b2 = -1;} // nicht über
if (data->board.field[b2] != me) b2 = -1; // Lücken
}
}

if (data->ball[1] != b1 || data->ball[2] != b2)
{
// Selektionen löschen

data->setsels = FALSE;
data->update_mode = SELSDRAW;
MUI_Redraw(obj, MADF_DRAWUPDATE);

// Neue setzen

data->ball[1] = b1;
data->ball[2] = b2;
data->setsels = TRUE;
data->update_mode = SELSDRAW;
MUI_Redraw(obj, MADF_DRAWUPDATE);
}

break;
} // End IDCMP_MOUSEMOVE

} // End switch Class
return(DoSuperMethodA(cl, obj, (Msg)msg));
}


/****************************************************************************************
Draw
****************************************************************************************/

SAVEDS ULONG Board_Draw(struct IClass* cl, Object* obj, struct MUIP_Draw* msg)
{
DoSuperMethodA(cl, obj, (Msg)msg);
if (!(msg->flags & (MADF_DRAWUPDATE + MADF_DRAWOBJECT))) return 0; // Überflüssig?

struct Board_Data* data = (Board_Data*)INST_DATA(cl,obj);
RastPort* rp = _rp(obj);
struct AreaInfo areainfo;
struct TmpRas tmp;

//APTR cliphandle = MUI_AddClipping(muiRenderInfo(obj), _mleft (obj), _mtop(obj),
// _mwidth(obj), _mheight(obj)); // Überflüssig?
int w = rp->BitMap->BytesPerRow * 8,
h = rp->BitMap->Rows;
PLANEPTR mem = AllocRaster(w, h);

InitArea(&areainfo, &data->areabuffer, 400);
rp->TmpRas = (struct TmpRas*)InitTmpRas(&tmp, mem, RASSIZE(w, h));
rp->AreaInfo = &areainfo;

/*
**
** DRAWOBJECT
**
*/

if (msg->flags & MADF_DRAWOBJECT)
{
data->left = _mleft (obj) + 5;
data->right = _mright (obj) - 5;
data->top = _mtop (obj) + 5;
data->bottom = _mbottom(obj) - 5;
data->width = data->right - data->left + 1;
data->height = data->bottom - data->top + 1;
data->mdx = _mwidth (obj) / 21; // Abstand zwischen Minikugelmittelpunkten
data->mdy = _mheight(obj) / 21; //
data->mrx = int((0.8 * data->mdx) / 2); // Minikugelradius
data->mry = int((0.8 * data->mdy) / 2); //
data->dx = data->width / 9; // Abstand zwischen Kugelmittelpunkten
data->dy = data->height / 9; //
data->rx = int((0.8 * data->dx) / 2); // Kugelradius
data->ry = int((0.8 * data->dy) / 2); //

data->diff = FALSE;
data->setsels = TRUE;
}


/*
**
** ALLDRAW
**
*/

if (data->update_mode == ALLDRAW || msg->flags & MADF_DRAWOBJECT)
{
/*
** New settings?
*/

if (data->newsettings)
{
Object* app = (Object*)xget(obj, MUIA_ApplicationObject);
Settings* s = (Settings*)xget(app, MUIA_Abacus_Settings);

if (data->pen1 != -1) MUI_ReleasePen(muiRenderInfo(obj), data->pen1);
if (data->pen2 != -1) MUI_ReleasePen(muiRenderInfo(obj), data->pen2);
if (data->pen3 != -1) MUI_ReleasePen(muiRenderInfo(obj), data->pen3);
if (data->pen4 != -1) MUI_ReleasePen(muiRenderInfo(obj), data->pen4);
data->pen1 = MUI_ObtainPen(muiRenderInfo(obj), &s->color1, 0);
data->pen2 = MUI_ObtainPen(muiRenderInfo(obj), &s->color2, 0);
data->pen3 = MUI_ObtainPen(muiRenderInfo(obj), &s->color3, 0);
data->pen4 = MUI_ObtainPen(muiRenderInfo(obj), &s->color4, 0);

data->dirs = s->dirs;
data->newsettings = FALSE;
}

/*
** Spielfeld
*/

for (int color = 0; color < 3; color++)
{
BOOL draw = FALSE;
for (int f = 0; f < 61; f++)
{
if (data->board.field[f] != data->last_board.field[f] || !data->diff)
{
if (color == 1 && data->board.field[f] == Board::white ||
color == 2 && data->board.field[f] == Board::black ||
color == 0 && data->board.field[f] == Board::empty )
{
int cx, cy;
data->GetCenterOf(f, cx, cy);
AreaEllipse(rp, cx, cy, data->rx, data->ry);
draw = TRUE;
}
}
}
if (draw)
{
switch(color)
{
case 0: SetAPen (rp, MUIPEN(data->pen3)); break;
case 1: SetAPen (rp, MUIPEN(data->pen1)); break;
case 2: SetAPen (rp, MUIPEN(data->pen2)); break;
}
AreaEnd(rp);
}
}

/*
** Minikugeln
*/

BYTE o = rp->AOlPen;
int mx = data->right - data->mrx, my ,i;

if (data->board.outBalls(Board::white) != data->last_board.outBalls(Board::white) || !data->diff)
{
SetAPen(rp, MUIPEN(data->pen1));
SetOPen(rp, MUIPEN(data->pen1));
my = data->top + data->mry;
for (i = 0; i < 6; i++)
{
if (i == data->board.outBalls(Board::white)) SetAPen(rp, 0);
AreaEllipse(rp, mx, my + data->mdy * i, data->mrx, data->mry);
AreaEnd(rp);
}
}

if (data->board.outBalls(Board::black) != data->last_board.outBalls(Board::black) || !data->diff)
{
SetAPen(rp, MUIPEN(data->pen2));
SetOPen(rp, MUIPEN(data->pen2));
my = data->bottom - data->mry;
for (i = 0; i < 6; i++)
{
if (i == data->board.outBalls(Board::black)) SetAPen(rp, 0);
AreaEllipse(rp, mx, my - data->mdy * i, data->mrx, data->mry);
AreaEnd(rp);
}
}

SetOPen(rp, o);

}

/*
**
** SELSDRAW
**
*/

if (data->update_mode == SELSDRAW || msg->flags & MADF_DRAWOBJECT)
{
/*
** Selektiere (de-)markieren
*/

for (int i = 0; i < 3; i++)
{
if (data->ball[i] != -1)
{
int cx, cy;
data->GetCenterOf(data->ball[i], cx, cy);
if (data->setsels)
{
SetAPen(rp, MUIPEN(data->pen4));
AreaEllipse(rp, cx, cy, int(data->rx / 2.5), int(data->ry / 2.5));
}
else
{
char c = data->board.field[data->ball[i]];

if (c == Board::white) SetAPen(rp, MUIPEN(data->pen1));
else if (c == Board::black) SetAPen(rp, MUIPEN(data->pen2));
else SetAPen(rp, MUIPEN(data->pen3));
AreaEllipse(rp, cx, cy, data->rx, data->ry);
}
AreaEnd(rp);
}
}

/*
** Zugmöglichkeiten anzeigen/löschen
*/

if (data->dirs && data->ball[0] != -1)
{
for (int dir = 0; dir < 6; dir++)
{
if (data->board.Test(data->ball[0], dir, data->ball[1], data->ball[2]) >= 0)
{
int n = Board::next[data->ball[0]][dir];
if (n != -1)
{
int cx, cy;
data->GetCenterOf(n, cx, cy);

if (data->setsels)
{
SetAPen(rp, MUIPEN(data->pen4));
AreaEllipse(rp, cx, cy, data->rx, data->ry);
AreaEnd(rp);
}

char c = data->board.field[n];
if (c == Board::white) SetAPen(rp, MUIPEN(data->pen1));
else if (c == Board::black) SetAPen(rp, MUIPEN(data->pen2));
else SetAPen(rp, MUIPEN(data->pen3));

if (data->setsels)
AreaEllipse(rp, cx, cy, data->rx - 2, data->ry - 2);
else
AreaEllipse(rp, cx, cy, data->rx, data->ry);
AreaEnd(rp);

}
}
}
}

}

rp->TmpRas = NULL;
rp->AreaInfo = NULL;
FreeRaster(mem, w, h);
rp->Flags &= ~AREAOUTLINE;
//MUI_RemoveClipping(muiRenderInfo(obj), cliphandle);

return(0);
}


/****************************************************************************************
New / Dispose
****************************************************************************************/

ULONG Board_New(struct IClass* cl, Object* obj, struct opSet* msg)
{
Board_Data tmp;

obj = (Object*)DoSuperNew(cl, obj, TAG_MORE, msg->ops_AttrList);
if (obj)
{
tmp.last_board = tmp.board;
tmp.pen1 = -1;
tmp.pen2 = -1;
tmp.pen3 = -1;
tmp.pen4 = -1;
tmp.ball[0] = -1;
tmp.ball[1] = -1;
tmp.ball[2] = -1;
struct Board_Data* data = (Board_Data*)INST_DATA(cl, obj);
*data = tmp;
}
return (ULONG)obj;
}


/****************************************************************************************
Set
****************************************************************************************/

ULONG Board_Set(struct IClass* cl, Object* obj, struct opSet* msg)
{
struct Board_Data* data = (Board_Data*)INST_DATA(cl, obj);
struct TagItem *tag;
tag = FindTagItem(MUIA_Board_Board, msg->ops_AttrList);
if (tag)
{
/*
** Selektionen löschen
*/

data->setsels = FALSE;
data->update_mode = SELSDRAW;
MUI_Redraw(obj, MADF_DRAWUPDATE);

/*
** Board zeichnen
*/

data->last_board = data->board;
data->board = *(Board*)tag->ti_Data;
data->diff = TRUE;
data->update_mode = ALLDRAW;
data->ball[0] = -1;
data->ball[1] = -1;
data->ball[2] = -1;
MUI_Redraw(obj, MADF_DRAWUPDATE);

/*
** Selektionen setzen
*/

data->setsels = TRUE;
data->update_mode = SELSDRAW;
MUI_Redraw(obj, MADF_DRAWUPDATE);

/*
** Richtigen Spieler setzen
*/

Object* win = (Object*)xget(obj, MUIA_WindowObject);
if (data->board.me == Board::white)
setatt(win, MUIA_BoardWindow_ActivePlayer, 1);
else
setatt(win, MUIA_BoardWindow_ActivePlayer, 2);

return TRUE;
}
return DoSuperMethodA(cl, obj, (Msg)msg);
}


/****************************************************************************************
Dispatcher
****************************************************************************************/

SAVEDS ASM ULONG Board_Dispatcher(REG(a0) struct IClass* cl,
REG(a2) Object* obj,
REG(a1) Msg msg)
{
switch(msg->MethodID)
{
case OM_NEW : return(Board_New (cl, obj, (opSet*)msg));
case OM_SET : return(Board_Set (cl, obj, (opSet*)msg));
case MUIM_Cleanup : return(Board_Cleanup (cl, obj, msg));
case MUIM_Setup : return(Board_Setup (cl, obj, msg));
case MUIM_HandleInput : return(Board_HandleInput (cl, obj, (MUIP_HandleInput*)msg));
case MUIM_AskMinMax : return(Board_AskMinMax (cl, obj, (MUIP_AskMinMax*)msg));
case MUIM_Draw : return(Board_Draw (cl, obj, (MUIP_Draw*)msg));

case MUIM_Board_NewSettings : return(Board_NewSettings (cl, obj, msg));
case MUIM_Board_Undo : return(Board_Undo (cl, obj, msg));
case MUIM_Board_Load : return(Board_Load (cl, obj, msg));
case MUIM_Board_Save : return(Board_Save (cl, obj, msg));
case MUIM_Board_NewGame : return(Board_NewGame (cl, obj, msg));
case MUIM_Board_Winner : return(Board_Winner (cl, obj, msg));
case MUIM_Board_ComputerMove: return(Board_ComputerMove(cl, obj, msg));
}
return(DoSuperMethodA(cl, obj, msg));
}

+ 80
- 0
BoardClass.hpp View File

@@ -0,0 +1,80 @@
/*
* This file is part of Abacus.
* Copyright (C) 1997 Kai Nickel
*
* Abacus is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Abacus is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Abacus. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef INCLUDE_BOARDCLASS_HPP
#define INCLUDE_BOARDCLASS_HPP
/****************************************************************************************
BoardClass.hpp
-----------------------------------------------------------------------------------------

CL_BoardClass (Area)

-----------------------------------------------------------------------------------------
02.01.1997
****************************************************************************************/

#include "System.hpp"

#include "MCC.hpp"
#include "Board.hpp"
#include "Tools.hpp"


extern MUI_CustomClass *CL_Board;

#define MUIA_Board_Board (TAGBASE_KAI | 0x1201) // [.S.]
#define MUIM_Board_NewSettings (TAGBASE_KAI | 0x1202)
#define MUIM_Board_Undo (TAGBASE_KAI | 0x1204)
#define MUIM_Board_Winner (TAGBASE_KAI | 0x1205)
#define MUIM_Board_Load (TAGBASE_KAI | 0x1206)
#define MUIM_Board_Save (TAGBASE_KAI | 0x1207)
#define MUIM_Board_NewGame (TAGBASE_KAI | 0x1208)
#define MUIM_Board_ComputerMove (TAGBASE_KAI | 0x1209)


struct Board_Data
{
Board board, last_board; // Spielfeld und letztes
int update_mode; //
BOOL setsels; // Selections setzen od. löschen
int ball[3]; // Selektierte Bälle
BOOL diff; // Zeichnen im Vgl. zum last_board;

BOOL newsettings;

void GetCenterOf(int, int&, int&); // Kreismittelpunkt von feld[nr] berechnen
int GetNrOf (int, int); // Feldindex der Mausposition berechnen
ULONG ActivePlayerNr(); // Akt. Spieler als Nummer

/*
** Graphik Context
*/

LONG pen1, pen2, pen3, pen4;
int dx, dy, rx, ry, mdx, mdy, mrx, mry,
left, right, top, bottom,
width, height;
WORD areabuffer[1000];
BOOL dirs; // Mögl. Züge anzeigen
};


SAVEDS ASM ULONG Board_Dispatcher(REG(a0) struct IClass* cl,
REG(a2) Object* obj,
REG(a1) Msg msg);
#endif

+ 263
- 0
BoardWindow.cpp View File

@@ -0,0 +1,263 @@
/*
* This file is part of Abacus.
* Copyright (C) 1997 Kai Nickel
*
* Abacus is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Abacus is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Abacus. If not, see <http://www.gnu.org/licenses/>.
*
*/
/****************************************************************************************
BoardWindow.cpp
-----------------------------------------------------------------------------------------

CL_BoardWindow (Window)

-----------------------------------------------------------------------------------------
03.01.1997
****************************************************************************************/

#include <pragma/gadtools_lib.h>

#include "BoardWindow.hpp"
#include "BoardClass.hpp"
#include "Abacus.hpp"
#include "Tools.hpp"
#include "Settings.hpp"
#include "Images.hpp"

#include "images/IMG_Start.c"
#include "images/IMG_Undo.c"
#include "images/IMG_Settings.c"
#include "images/IMG_Quit.c"
#include "images/IMG_Rules.c"

MUI_CustomClass *CL_BoardWindow;


/****************************************************************************************
Quit
****************************************************************************************/

ULONG BoardWindow_Quit(struct IClass* cl, Object* obj, Msg msg)
{
struct BoardWindow_Data* data = (BoardWindow_Data*)INST_DATA(cl, obj);
Object* app = (Object*)xget(obj, MUIA_ApplicationObject);
if (MUI_RequestA(app, obj, 0, GetStr(MSG_QUIT_TITLE),
GetStr(MSG_QUIT_GADGETS), GetStr(MSG_QUIT_TEXT), NULL) == 1)
DoMethod(app, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);
return 0;
}


/****************************************************************************************
NewSettings
****************************************************************************************/

ULONG BoardWindow_NewSettings(struct IClass* cl, Object* obj, Msg msg)
{
struct BoardWindow_Data* data = (BoardWindow_Data*)INST_DATA(cl, obj);
Object* app = (Object* )xget(obj, MUIA_ApplicationObject);
Settings* s = (Settings*)xget(app, MUIA_Abacus_Settings);
DoMethod(data->Board, MUIM_Board_NewSettings);

setatt(data->TX_Player1, MUIA_Text_Contents , s->name1 );
setatt(data->TX_Player2, MUIA_Text_Contents , s->name2 );
setatt(data->PD_Player1, MUIA_Pendisplay_Spec, &s->color1);
setatt(data->PD_Player2, MUIA_Pendisplay_Spec, &s->color2);

return 0;
}