Compare commits
6 Commits
eae47faed0
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
dedf852090 | ||
|
5d4b3c55c6 | ||
|
0dd62af930 | ||
|
99f5f4bbfa | ||
|
557a60dc6d | ||
|
3ca479a251 |
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024 Maximilian Moser
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
26
README.md
Normal file
26
README.md
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# Maxman
|
||||||
|
|
||||||
|
Maxman is a simple game inspired by classics such as `Pacman`, `Achtung, die Kurve!` (also known as `Zatacka`), and `Snake`.
|
||||||
|
|
||||||
|
The basic goal is to grow by eating the food lying around until you're big enough to eat your competitors.
|
||||||
|
|
||||||
|
|
||||||
|
## Getting started
|
||||||
|
|
||||||
|
The game's requirements are listed in `Pipfile`, so you can just install them with `pipenv install`.
|
||||||
|
To run the game after installing the requirements, use `pipenv run ./maxman.py`
|
||||||
|
|
||||||
|
|
||||||
|
## Controls
|
||||||
|
|
||||||
|
Per default, each player has their own key bindings (up, left, down, right):
|
||||||
|
* Maxman (yellow): `w`, `a`, `s`, `d`
|
||||||
|
* Blackman (black): `i`, `j`, `k`, `l`
|
||||||
|
|
||||||
|
Other key bindings are:
|
||||||
|
* `SPACE`: Pause/resume
|
||||||
|
|
||||||
|
|
||||||
|
## Playing against AI
|
||||||
|
|
||||||
|
If you want to play against the AI instead of other players, supply the corresponding CLI flag: `pipenv run ./maxman.py --ai <number of AI players>`
|
55
maxman.py
Normal file → Executable file
55
maxman.py
Normal file → Executable file
@@ -1,8 +1,10 @@
|
|||||||
|
#!/bin/env python3
|
||||||
|
|
||||||
import abc
|
import abc
|
||||||
|
import argparse
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import math
|
import math
|
||||||
import random
|
import random
|
||||||
import sys
|
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
import pygame
|
import pygame
|
||||||
@@ -113,11 +115,14 @@ class AI:
|
|||||||
return
|
return
|
||||||
|
|
||||||
target = self.target
|
target = self.target
|
||||||
if random.random() * 100 < 10:
|
if (target and target.size > self.man.size) or random.random() * 100 < 10:
|
||||||
target = None
|
target = None
|
||||||
|
|
||||||
if target is None:
|
if target is None:
|
||||||
if targets := [e for e in self.enemies or [] if e.size < self.man.size]:
|
targets = [
|
||||||
|
e for e in self.enemies or [] if e.alive and e.size < self.man.size
|
||||||
|
]
|
||||||
|
if targets:
|
||||||
target = random.choice(targets)
|
target = random.choice(targets)
|
||||||
|
|
||||||
if target is None:
|
if target is None:
|
||||||
@@ -155,10 +160,9 @@ dt = 0
|
|||||||
|
|
||||||
# set up board
|
# set up board
|
||||||
sw, sh = screen.get_width(), screen.get_height()
|
sw, sh = screen.get_width(), screen.get_height()
|
||||||
ai = AI()
|
|
||||||
maxman = Man(pygame.Vector2(sw / 4, sh / 4), name="Maxman")
|
maxman = Man(pygame.Vector2(sw / 4, sh / 4), name="Maxman")
|
||||||
blackman = Man(
|
blackman = Man(
|
||||||
pygame.Vector2(sw * 0.75, sh * 0.75),
|
pygame.Vector2(sw * 0.75, sh * 0.25),
|
||||||
name="Blackman",
|
name="Blackman",
|
||||||
color="black",
|
color="black",
|
||||||
key_up=pygame.K_i,
|
key_up=pygame.K_i,
|
||||||
@@ -166,11 +170,41 @@ blackman = Man(
|
|||||||
key_left=pygame.K_j,
|
key_left=pygame.K_j,
|
||||||
key_right=pygame.K_l,
|
key_right=pygame.K_l,
|
||||||
)
|
)
|
||||||
players = [maxman, blackman]
|
chrisman = Man(
|
||||||
|
pygame.Vector2(sw * 0.25, sh * 0.75),
|
||||||
|
name="Chrisman",
|
||||||
|
color="red",
|
||||||
|
key_up=pygame.K_UP,
|
||||||
|
key_down=pygame.K_DOWN,
|
||||||
|
key_left=pygame.K_LEFT,
|
||||||
|
key_right=pygame.K_RIGHT,
|
||||||
|
)
|
||||||
|
manman = Man(
|
||||||
|
pygame.Vector2(sw * 0.75, sh * 0.75),
|
||||||
|
name="Manman",
|
||||||
|
color="green",
|
||||||
|
key_up=pygame.K_KP_8,
|
||||||
|
key_down=pygame.K_KP_2,
|
||||||
|
key_left=pygame.K_KP_4,
|
||||||
|
key_right=pygame.K_KP_6,
|
||||||
|
)
|
||||||
|
players = [maxman, blackman, chrisman, manman]
|
||||||
food = Food.new()
|
food = Food.new()
|
||||||
|
|
||||||
if any([arg in ["--ai", "-a"] for arg in sys.argv]):
|
parser = argparse.ArgumentParser()
|
||||||
ai.hook(blackman)
|
parser.add_argument(
|
||||||
|
"--ai",
|
||||||
|
type=int,
|
||||||
|
choices=[0, 1, 2, 3, 4],
|
||||||
|
default=1,
|
||||||
|
help="number of AI players",
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
ais = []
|
||||||
|
for i in range(args.ai):
|
||||||
|
ai = AI()
|
||||||
|
ai.hook(players[-i - 1])
|
||||||
|
ais.append(ai)
|
||||||
|
|
||||||
while running:
|
while running:
|
||||||
# check recent events
|
# check recent events
|
||||||
@@ -204,6 +238,7 @@ while running:
|
|||||||
for p in players:
|
for p in players:
|
||||||
for op in players:
|
for op in players:
|
||||||
if p != op and p.can_eat(op):
|
if p != op and p.can_eat(op):
|
||||||
|
op.alive = False
|
||||||
players.remove(op)
|
players.remove(op)
|
||||||
|
|
||||||
if p.can_eat(food):
|
if p.can_eat(food):
|
||||||
@@ -220,7 +255,9 @@ while running:
|
|||||||
)
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
ai.decide()
|
for ai in ais:
|
||||||
|
ai.decide()
|
||||||
|
|
||||||
for p in players:
|
for p in players:
|
||||||
p.handle_input(keys, dt)
|
p.handle_input(keys, dt)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user