Skip to content

Commit caf94f8

Browse files
committed
Meg: Ready for live testing
1 parent 2796711 commit caf94f8

File tree

6 files changed

+772
-2
lines changed

6 files changed

+772
-2
lines changed

locales/en/apgames.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@
9898
"margo": "Margo is a stacking Go variant. Players may not pass. The game ends when one player is not able to move, and the player with the most balls on the board wins.",
9999
"mattock": "In Mattock, you play miners digging corridors through the rock. You can't dig too closely together though, or the mine will collapse. To win, trap your opponent so they run out of space to mine.",
100100
"mchess": "A Looney pyramid game for two players played on half of a standard chess board. It is a chess-like strategy game in which location, rather than piece color, determines which pieces you may move. Like Chess, each type of piece has its own way of moving, and you capture by moving onto an opponent's square; but unlike Chess, you can only move pieces sitting in your own quadrant, and only attack those in other quadrants, which may include your own former pieces. The game ends when someone runs out of pieces, and the winner is the player who captured the most points.",
101+
"meg": "In this push-your-luck game, players place receivers until someone \"takes the ball.\" The defense then starts placing blockers while the offense can place more receivers or take a shot. Offense wins by successfully shooting the ball between two pieces before the clock runs out.",
101102
"meridians": "Meridians is a territorial game with the goal of annihilating the opponent's stones. Starting with an empty board, players alternate turns placing a stone on an empty point as in Go. Groups should be \"seen\" by other friendly stone through a straight path or they will be removed on your opponent's turn.",
102103
"mimic": "A game where enemy pieces mimic your moves while you race to be the first player to reach the back row.",
103104
"mirador": "Mirador is a fast and exhilarating connection game played on a 27 x 27 square grid by placing 2 x 2 squares to represent watchtowers. It uses line-of-sight connections and equivalent goals (making it more of a race than a pure connection game).",
@@ -2746,6 +2747,10 @@
27462747
"GROUPSIZES": "Group sizes",
27472748
"jacynth": "Influence tokens",
27482749
"majorities": "Scores (─, ⟋, ⟍)",
2750+
"meg": {
2751+
"OFFENSE": "Offensive player",
2752+
"COUNTDOWN": "Plies remaining"
2753+
},
27492754
"PHASE": "Phase",
27502755
"PIECESINHAND": "Pieces in hand",
27512756
"PIECESINHANDSTASH": "Pieces in hand / stash",
@@ -3802,6 +3807,13 @@
38023807
"VALID_MOVE_counter": "Looks like a valid move.",
38033808
"VALID_MOVE_nocounter": "Looks like a valid move. You may add an asterisk (*) to the end of the move to \"call the clock\" if you believe the game is deadlocked."
38043809
},
3810+
"meg": {
3811+
"INITIAL_INSTRUCTIONS_defense": "Place a blocker in any empty space.",
3812+
"INITIAL_INSTRUCTIONS_offense": "Place a receiver in any empty space or select the ball to make a shot.",
3813+
"INITIAL_INSTRUCTIONS_setup": "Place a receiver in any empty space or select an existing piece to \"take the ball\" and play as offense.",
3814+
"PARTIAL": "Continue selecting receivers or click \"Complete move\" to stop the shot here.",
3815+
"SHOT_START": "Select a receiver."
3816+
},
38053817
"meridians": {
38063818
"INITIAL_INSTRUCTIONS": "Place a piece on the board.",
38073819
"INITIAL_INSTRUCTIONS_PASS": "Either invoke the pie rule to play as first player or pass to play as second. If pie was already invoked, your only option is to pass.",

locales/en/apresults.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@
120120
"majorities_H": "{{player}} claimed the horizontal direction.",
121121
"majorities_A": "{{player}} claimed the ascending direction.",
122122
"majorities_D": "{{player}} claimed the descending direction.",
123+
"meg": "{{player}} has taken the ball and placed it at {{where}}.",
123124
"penguin": "The penguin at {{where}} claimed the ball!",
124125
"veletas": "Shooter at {{where}} is trapped and is claimed by {{who}}."
125126
},
@@ -245,6 +246,7 @@
245246
"hexentafl_king": "{{player}} moved the king from {{from}} to {{to}}.",
246247
"iqishiqi": "{{player}} moved neutral stone {{from}} to {{to}}.",
247248
"mattock": "{{player}} moved a miner from {{from}} to {{to}}.",
249+
"meg": "{{player}} passed the ball from {{from}} to {{to}}.",
248250
"monkey_queen": "{{player}} moved their queen from {{from}} to {{to}}.",
249251
"monkey_single": "{{player}} moved a singleton from {{from}} to {{to}}.",
250252
"multiple": "{{player}} made the following moves: {{moves}}.",
@@ -317,6 +319,8 @@
317319
"logger_plant": "{{player}} planted a sapling at {{where}}.",
318320
"logger_spawn": "A new sapling sprouted at {{where}}.",
319321
"mattock": "{{player}} placed a miner at {{where}}.",
322+
"meg_cap": "{{player}} placed a blocker at {{where}}.",
323+
"meg_cup": "{{player}} placed a receiver at {{where}}.",
320324
"mine": "{{player}} placed one of their own pieces at {{where}}.",
321325
"moonsquad": "{{player}} placed a squad at {{where}}.",
322326
"neutral": "A neutral piece was placed at {{where}}.",

src/common/plotting.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,3 +145,59 @@ export const circle2poly = (cx: number, cy: number, r: number, steps = 64): [num
145145
export const distFromCircle = (circle: {cx: number, cy: number, r: number}, point: IPoint): number => {
146146
return Math.abs(Math.sqrt((point.x - circle.cx)**2 + (point.y - circle.cy)**2) - circle.r);
147147
}
148+
149+
// determines if point q lies on the segment pr
150+
export const pointOnSegment = (p: IPoint, q: IPoint, r: IPoint): boolean => {
151+
if (q.x <= Math.max(p.x, r.x) &&
152+
q.x >= Math.min(p.x, r.x) &&
153+
q.y <= Math.max(p.y, r.y) &&
154+
q.y >= Math.min(p.y, r.y)) {
155+
return true;
156+
}
157+
return false;
158+
}
159+
160+
// To find orientation of ordered triplet (p, q, r).
161+
// The function returns following values
162+
// 0 --> p, q and r are collinear
163+
// 1 --> Clockwise
164+
// 2 --> Counterclockwise
165+
export const pointOrientation = (p: IPoint, q: IPoint, r: IPoint) : 0|1|2 => {
166+
// See https://www.geeksforgeeks.org/orientation-3-ordered-points/
167+
// for details of below formula.
168+
const val = (q.y - p.y) * (r.x - q.x) -
169+
(q.x - p.x) * (r.y - q.y);
170+
171+
if (val === 0) return 0; // collinear
172+
return (val > 0)? 1 : 2; // clock or counterclock wise
173+
}
174+
175+
// The main function that returns true if line segment 'p1q1'
176+
// and 'p2q2' intersect.
177+
export const linesIntersect = (p1: IPoint, q1: IPoint, p2: IPoint, q2: IPoint): boolean => {
178+
// Find the four orientations needed for general and
179+
// special cases
180+
const o1 = pointOrientation(p1, q1, p2);
181+
const o2 = pointOrientation(p1, q1, q2);
182+
const o3 = pointOrientation(p2, q2, p1);
183+
const o4 = pointOrientation(p2, q2, q1);
184+
185+
// General case
186+
if (o1 !== o2 && o3 !== o4)
187+
return true;
188+
189+
// Special Cases
190+
// p1, q1 and p2 are collinear and p2 lies on segment p1q1
191+
if (o1 === 0 && pointOnSegment(p1, p2, q1)) return true;
192+
193+
// p1, q1 and q2 are collinear and q2 lies on segment p1q1
194+
if (o2 === 0 && pointOnSegment(p1, q2, q1)) return true;
195+
196+
// p2, q2 and p1 are collinear and p1 lies on segment p2q2
197+
if (o3 === 0 && pointOnSegment(p2, p1, q2)) return true;
198+
199+
// p2, q2 and q1 are collinear and q1 lies on segment p2q2
200+
if (o4 === 0 && pointOnSegment(p2, q1, q2)) return true;
201+
202+
return false; // Doesn't fall in any of the above cases
203+
}

src/games/index.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ import { ChurnGame, IChurnState } from "./churn";
181181
import { PenguinGame, IPenguinState } from "./penguin";
182182
import { OwlmanGame, IOwlmanState } from "./owlman";
183183
import { SquaredanceGame, ISquaredanceState } from "./squaredance";
184+
import { MegGame, IMegState } from "./meg";
184185

185186
export {
186187
APGamesInformation, GameBase, GameBaseSimultaneous, IAPGameState,
@@ -364,6 +365,7 @@ export {
364365
PenguinGame, IPenguinState,
365366
OwlmanGame, IOwlmanState,
366367
SquaredanceGame, ISquaredanceState,
368+
MegGame, IMegState,
367369
};
368370

369371
const games = new Map<string, typeof AmazonsGame | typeof BlamGame | typeof CannonGame |
@@ -426,7 +428,7 @@ const games = new Map<string, typeof AmazonsGame | typeof BlamGame | typeof Cann
426428
typeof StorisendeGame | typeof TraxGame | typeof AmoebaGame |
427429
typeof YavalathGame | typeof ConspirateursGame | typeof CatapultGame |
428430
typeof BasaltGame | typeof ChurnGame | typeof PenguinGame |
429-
typeof OwlmanGame | typeof SquaredanceGame
431+
typeof OwlmanGame | typeof SquaredanceGame | typeof MegGame
430432
>();
431433
// Manually add each game to the following array
432434
[
@@ -455,7 +457,7 @@ const games = new Map<string, typeof AmazonsGame | typeof BlamGame | typeof Cann
455457
HulaGame, KonaneGame, BlastRadiusGame, FramesGame, LoggerGame, SubdivisionGame, PylonGame,
456458
MoonSquadGame, JacynthGame, Pigs2Game, TerraceGame, CubeoGame, StorisendeGame, TraxGame,
457459
AmoebaGame, YavalathGame, ConspirateursGame, CatapultGame, BasaltGame, ChurnGame, PenguinGame,
458-
OwlmanGame, SquaredanceGame,
460+
OwlmanGame, SquaredanceGame, MegGame,
459461
].forEach((g) => {
460462
if (games.has(g.gameinfo.uid)) {
461463
throw new Error("Another game with the UID '" + g.gameinfo.uid + "' has already been used. Duplicates are not allowed.");
@@ -827,6 +829,8 @@ export const GameFactory = (game: string, ...args: any[]): GameBase|GameBaseSimu
827829
return new OwlmanGame(...args);
828830
case "squaredance":
829831
return new SquaredanceGame(...args);
832+
case "meg":
833+
return new MegGame(...args);
830834
}
831835
return;
832836
}

0 commit comments

Comments
 (0)