Skip to content
Snippets Groups Projects
Commit 1d43c796 authored by ameara's avatar ameara
Browse files

Resolve "Rename Lama to wizard"

parent 942b30f4
No related branches found
No related tags found
1 merge request!2Resolve "Rename Lama to wizard"
Showing
with 37 additions and 37 deletions
cmake_minimum_required(VERSION 3.15)
project(Lama) # your project name
project(Wizard) # your project name
set(CMAKE_CXX_STANDARD 20)
......@@ -11,7 +11,7 @@ include(${wxWidgets_USE_FILE})
# define a variable CLIENT_SOURCE_FILES that contains the paths to all source files required to compile the client executable
set(CLIENT_SOURCE_FILES
src/client/main.cpp
src/client/app/Lama.cpp src/client/app/Lama.h
src/client/app/Wizard.cpp src/client/app/Wizard.h
src/client/GameController.cpp src/client/GameController.h
# UI
src/client/windows/GameWindow.cpp src/client/windows/GameWindow.h
......@@ -86,31 +86,31 @@ set(SERVER_SOURCE_FILES
# set source files for client-executable
add_executable(Lama-client ${CLIENT_SOURCE_FILES})
add_executable(Wizard-client ${CLIENT_SOURCE_FILES})
# set compile directives for client-executable
target_compile_definitions(Lama-client PRIVATE LAMA_CLIENT=1 RAPIDJSON_HAS_STDSTRING=1)
target_compile_definitions(Wizard-client PRIVATE WIZARD_CLIENT=1 RAPIDJSON_HAS_STDSTRING=1)
# link with wxWidgets
target_link_libraries(Lama-client ${wxWidgets_LIBRARIES})
target_link_libraries(Wizard-client ${wxWidgets_LIBRARIES})
# Comment out if you don't want to print network-related messages into the console
target_compile_definitions(Lama-client PRIVATE PRINT_NETWORK_MESSAGES=1)
target_compile_definitions(Wizard-client PRIVATE PRINT_NETWORK_MESSAGES=1)
# set source files for server-executable
add_executable(Lama-server ${SERVER_SOURCE_FILES})
add_executable(Wizard-server ${SERVER_SOURCE_FILES})
# set compile directives for server-executable
target_compile_definitions(Lama-server PRIVATE LAMA_SERVER=1 RAPIDJSON_HAS_STDSTRING=1)
target_compile_definitions(Wizard-server PRIVATE WIZARD_SERVER=1 RAPIDJSON_HAS_STDSTRING=1)
# Comment out if you don't want to print network-related messages into the console
target_compile_definitions(Lama-server PRIVATE PRINT_NETWORK_MESSAGES=1)
target_compile_definitions(Wizard-server PRIVATE PRINT_NETWORK_MESSAGES=1)
# linking to sockpp
if(WIN32)
message("Detected Win32")
target_link_libraries(Lama-client ${CMAKE_SOURCE_DIR}/sockpp/cmake-build-debug/sockpp-static.lib)
target_link_libraries(Lama-server ${CMAKE_SOURCE_DIR}/sockpp/cmake-build-debug/sockpp-static.lib)
target_link_libraries(Wizard-client ${CMAKE_SOURCE_DIR}/sockpp/cmake-build-debug/sockpp-static.lib)
target_link_libraries(Wizard-server ${CMAKE_SOURCE_DIR}/sockpp/cmake-build-debug/sockpp-static.lib)
# Necessary to get sockets working under Windows (with MingW)
target_link_libraries(Lama-client wsock32 ws2_32)
target_link_libraries(Wizard-client wsock32 ws2_32)
elseif(APPLE)
message("Detected macOS")
......@@ -118,8 +118,8 @@ elseif(APPLE)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(Lama-client ${CMAKE_SOURCE_DIR}/sockpp/cmake-build-debug/libsockpp.dylib Threads::Threads)
target_link_libraries(Lama-server ${CMAKE_SOURCE_DIR}/sockpp/cmake-build-debug/libsockpp.dylib Threads::Threads)
target_link_libraries(Wizard-client ${CMAKE_SOURCE_DIR}/sockpp/cmake-build-debug/libsockpp.dylib Threads::Threads)
target_link_libraries(Wizard-server ${CMAKE_SOURCE_DIR}/sockpp/cmake-build-debug/libsockpp.dylib Threads::Threads)
else()
message("Not Win32 or macOS, so probably Linux")
......@@ -127,8 +127,8 @@ else()
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(Lama-client ${CMAKE_SOURCE_DIR}/sockpp/cmake-build-debug/libsockpp.so Threads::Threads)
target_link_libraries(Lama-server ${CMAKE_SOURCE_DIR}/sockpp/cmake-build-debug/libsockpp.so Threads::Threads)
target_link_libraries(Wizard-client ${CMAKE_SOURCE_DIR}/sockpp/cmake-build-debug/libsockpp.so Threads::Threads)
target_link_libraries(Wizard-server ${CMAKE_SOURCE_DIR}/sockpp/cmake-build-debug/libsockpp.so Threads::Threads)
endif()
# copy assets (images) to binary directory
......@@ -137,9 +137,9 @@ file(INSTALL assets DESTINATION ${CMAKE_BINARY_DIR})
set(CMAKE_CXX_FLAGS "--coverage")
# set source files for server-library
add_library(Lama-lib ${SERVER_SOURCE_FILES})
add_library(Wizard-lib ${SERVER_SOURCE_FILES})
# set compile directives for server-library
target_compile_definitions(Lama-lib PRIVATE LAMA_SERVER=1 RAPIDJSON_HAS_STDSTRING=1)
target_compile_definitions(Wizard-lib PRIVATE WIZARD_SERVER=1 RAPIDJSON_HAS_STDSTRING=1)
add_subdirectory(googletest)
add_subdirectory(unit-tests)
\ No newline at end of file
# Lama
# wizard
This is a simple C++ implementation of the game "Lama" by AMIGO. You can read the game's rules [here](https://www.amigo.games/content/ap/rule/19420--031-2019-Lama_Manual_002_LAYOUT[1].pdf). The implementation features a client/server architecture for multiplayer scenarios.
This is a simple C++ implementation of the game "Wizard" by AMIGO. You can read the game's rules [here](https://www.amigo.games/content/ap/rule/19420--031-2019-Wizard_Manual_002_LAYOUT[1].pdf). The implementation features a client/server architecture for multiplayer scenarios.
It uses [wxWidgets](https://www.wxwidgets.org/) for the GUI, [sockpp](https://github.com/fpagliughi/sockpp) for the network interface, [rapidjson](https://rapidjson.org/md_doc_tutorial.html) for object serialization, and [googletest](https://github.com/google/googletest) for the unit tests.
![Lama-logo](./assets/lama_logo.png?raw=true)
![Wizard-logo](./assets/wizard_logo.png?raw=true)
This is a template project for the students of the course Software Engineering. In order to adapt this template to a different game, you will only need knowledge in wxWidgets and maybe about some basic functions of rapidjson to serialize certain data types. By sticking to the template you won't need to dig into sockpp at all.
......@@ -37,18 +37,18 @@ Execute the following commands in a console:
2. Click `File > Open...` and there select the **/sockpp** folder of this project
3. Click `Build > Build all in 'Debug'`
4. Wait until sockpp is compiled (from now on you never have to touch sockpp again ;))
5. Click `File > Open...` select the **/cse-lama-example-project** folder
5. Click `File > Open...` select the **/cse-wizard-example-project** folder
6. Click `Build > Build all in 'Debug'`
7. Wait until Lama-server, Lama-client and Lama-tests are compiled
7. Wait until Wizard-server, Wizard-client and Wizard-tests are compiled
## 2. Run the Game
1. Open a console in the project folder, navigate into "cmake-build-debug" `cd cmake-build-debug`
2. Run server `./Lama-server`
3. In new consoles run as many clients as you want players `./Lama-client`
2. Run server `./Wizard-server`
3. In new consoles run as many clients as you want players `./Wizard-client`
## 3. Run the Unit Tests
1. CLion should automatically create a Google Test configuration Lama-tests which will run all tests. See [Google Test run/debug configuration](https://www.jetbrains.com/help/clion/creating-google-test-run-debug-configuration-for-test.html#gtest-config) for more information.
2. From the list on the main toolbar, select the configuration Lama-tests.
1. CLion should automatically create a Google Test configuration Wizard-tests which will run all tests. See [Google Test run/debug configuration](https://www.jetbrains.com/help/clion/creating-google-test-run-debug-configuration-for-test.html#gtest-config) for more information.
2. From the list on the main toolbar, select the configuration Wizard-tests.
3. Click ![run](https://resources.jetbrains.com/help/img/idea/2021.1/artwork.studio.icons.shell.toolbar.run.svg) or press `Shift+F10`.
You can run individual tests or test suites by opening the corresponding file in the **/unit-tests** folder and clicking ![run](https://resources.jetbrains.com/help/img/idea/2021.1/artwork.studio.icons.shell.toolbar.run.svg) next to the test method or class. For more information on testing in CLion read the [documentation](https://www.jetbrains.com/help/clion/performing-tests.html).
......@@ -59,9 +59,9 @@ You don't need to look at the **/sockpp**, **/rapidjson** or **/googletest** fol
The code for the game can be found in **/src**, where it is separated into following folders:
- **/client** contains only code that is used on the client side (e.g. UI, sending messages)
- **/common** contains code that is shared between server and client.
- **/exceptions** contains the exception class used on server and client side. You don't need to change anything in here (unless you want to rename the LamaException class ;))
- **/game_state** contains the `game_state` that is synchronized between client and server. We use the [conditional pre-compile directive](https://www.cplusplus.com/doc/tutorial/preprocessor/) LAMA_SERVER to enable certain parts of the code only on the server side. Namely, these are the state update functions, as they should only happen on the server. The client simply reflects the current game state as sent by the server without modifying it directly.
- **/network** contains all the messages that are being passed between client and server. We use the LAMA_CLIENT pre-compile directive to make `server_repsonses` only executable on the client side (through the function `Process()`) .
- **/exceptions** contains the exception class used on server and client side. You don't need to change anything in here (unless you want to rename the WizardException class ;))
- **/game_state** contains the `game_state` that is synchronized between client and server. We use the [conditional pre-compile directive](https://www.cplusplus.com/doc/tutorial/preprocessor/) WIZARD_SERVER to enable certain parts of the code only on the server side. Namely, these are the state update functions, as they should only happen on the server. The client simply reflects the current game state as sent by the server without modifying it directly.
- **/network** contains all the messages that are being passed between client and server. We use the WIZARD_CLIENT pre-compile directive to make `server_repsonses` only executable on the client side (through the function `Process()`) .
- **/serialization** contains base classes for serializing `game_state`, `client_request` and `server_response` objects. **Serialization** is the process of transforming an object instance into a string that can be sent over a network, where the receiver deserializes it, i.e. recreates the object from the string. If you are interested, [read me on Wikipedia](https://en.wikipedia.org/wiki/Serialization).
- **/server** contains only code that is relevant for the server (e.g. player management, game instance management, receiving messages)
......@@ -180,10 +180,10 @@ if (json.HasMember("type") && json["type"].IsString()) {
else if (...) {
...
} else {
throw LamaException("Encountered unknown ClientRequest type " + type);
throw WizardException("Encountered unknown ClientRequest type " + type);
}
}
throw LamaException("Could not determine type of ClientRequest. JSON was:\n" + json_utils::to_string(&json));
throw WizardException("Could not determine type of ClientRequest. JSON was:\n" + json_utils::to_string(&json));
```
Therefore, when you implement your own `client_request` subclasses, remember to add a new element into the `RequestType` enum to define your new request type. You will also have to add an entry for this new RequestType in the two unordered_maps `_string_to_request_type`, resp. `_request_type_to_string` in the `client_request` base-class. Once this is done, you can add a check for your new `RequestType` element in the `from_json(...)` function of the `client_request` base-class and call the specialized `from_json(...)` function of your subclass from there.
......@@ -221,7 +221,7 @@ play_card_request* play_card_request::from_json(const rapidjson::Value& json) {
// invoke deserialization constructor
return new play_card_request(props, json["card_id"].GetString());
} else {
throw LamaException("Could not find 'card_id' in play_card_request");
throw WizardException("Could not find 'card_id' in play_card_request");
}
}
```
......@@ -261,7 +261,7 @@ bool game_instance::start_game(player* player, std::string &err) {
By default, the server (specifically, the server_network_manager) will print every valid message that it receives to the console. In order for this to work in your project as well, you have to make sure that your CMake file contains a line, where the preprocessor variable PRINT_NETWORK_MESSAGES is defined for your server executable.
```
target_compile_definitions(Lama-server PRIVATE PRINT_NETWORK_MESSAGES=1)
target_compile_definitions(Wizard-server PRIVATE PRINT_NETWORK_MESSAGES=1)
```
If a wrongly formatted message arrives at the server, it will print an error message with the received message string to the console, no matter if PRINT_NETWORK_MESSAGES is defined or not.
......@@ -330,7 +330,7 @@ The `game_state` inherits from `unique_serializable`, which essentially requires
On the client side, the new `game_state` is then passed to the `updateGameState(game_state*)` function of the `GameController` class, which performs a redraw of the GUI.
Since you will have to add your own properties to the `game_state` class (and probably create other classes that inherit from `unique_serializable` to add to your game_state), we want to shortly elaborate how the serialization and deserialization works for subclasses of `unique_serializable`. It's very similar to the `client_request` class discussed earlier. Here is how the `write_into_json(...)` function is implemented in the `game_state` class of Lama. **Don't be shocked by the lengthy code. It's only a lot of repetition for each class property** :
Since you will have to add your own properties to the `game_state` class (and probably create other classes that inherit from `unique_serializable` to add to your game_state), we want to shortly elaborate how the serialization and deserialization works for subclasses of `unique_serializable`. It's very similar to the `client_request` class discussed earlier. Here is how the `write_into_json(...)` function is implemented in the `game_state` class of Wizard. **Don't be shocked by the lengthy code. It's only a lot of repetition for each class property** :
```cpp
void game_state::write_into_json(rapidjson::Value &json,
......@@ -421,7 +421,7 @@ game_state* game_state::from_json(const rapidjson::Value &json) {
serializable_value<int>::from_json(json["round_number"].GetObject()),
serializable_value<int>::from_json(json["starting_player_idx"].GetObject()));
} else {
throw LamaException("Failed to deserialize game_state. Required entries were missing.");
throw WizardException("Failed to deserialize game_state. Required entries were missing.");
}
}
```
......@@ -445,7 +445,7 @@ Here is a list of the most important elements that you will need to create your
* __Application core__
* __`wxIMPLEMENT_APP()`__: In order to properly interact with the operating system's GUI, wxWidgets takes over the control flow of your application. wxWidgets therefore has its own `main()` function, that you can reference with the macro `wxIMPLEMENT_APP(wxApp*)`.
* __`wxApp`__: The core class of your application must inherit from the `wxApp` class. wxWidgets will call the `OnInit()` function when starting the application. You can find the example project's implementation in `src/client/app/Lama`.
* __`wxApp`__: The core class of your application must inherit from the `wxApp` class. wxWidgets will call the `OnInit()` function when starting the application. You can find the example project's implementation in `src/client/app/Wizard`.
* __Windows__
* __`wxFrame`__: Each window of your application must inherit from the `wxFrame` class. The example project has one window which you can find here: `src/client/windows/GameWindow`
* __GUI elements__
......
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment